当前位置: 首页 > news >正文

C++基础语法:STL之容器(5)--序列容器中的list(二)

前言
     

         "打牢基础,万事不愁" .C++的基础语法的学习

引入

        序列容器的学习.以<C++ Prime Plus> 6th Edition(以下称"本书")内容理解

        本书中容器内容不多只有几页.最好是有数据结构方面的知识积累,如果没有在学的同时补上

         接上一篇C++基础语法:STL之容器(4)--序列容器中的list(一)-CSDN博客

list(双向链表)  

         本书内容解读  

         第3部分除序列和可反转容器的函数外,list模板类还包含了链表专用的成员函数。表16.9列出了其中一些(有关STL方法和函数的完整列表,请参见附录G)。通常不必担心Alloc模板参数,因为它有默认值。

          ----看见了STL中的list,发现和自己写的不太一样,他有两个参数,表示为list<T,Alloc>,不过感觉问题也不是很大,代码主要说的是思路.

         照着成员函数的说明当成需求,前面是给出的函数原型,试着写一写算法.

        merge()合并算法看起来有点复杂,不写;remove前面有个相同名称的函数,因为想要调用之前的remove()函数,所以把他改为removeValue;splice()要用到迭代器,不写.把前面的容器类定义拿过来


template<class T>
class list{enum{MAX=10}int lsize;                        //list最大元素数量int items;                        //list内当前的元素个数class Node{                       //声明结点类public:                           //结点数据向外部类公开T t;Node *front;Node *next;Node(T val):t(val),front(0),next(0){}Node(){}                      //默认构造函数,为初始化时使用}Node* first;Node* last;
public:list(int num=MAX);                //构造函数   void add(Node* n,T& t);           //添加元素t到结点n后面T remove(Node* n);                //删除地址为n的结点//下面三个是将要实现的函数void removeValue(const T& val);   //删除val的所有实例void sort();                      //使用<运算符对链表进行排序Node* findNode(const T& t);       //排序中用到的函数void unique();                    //将连续的相同元素压缩成单个元素
}

         注意:下列代码为了练手,试图重现逻辑,不保证准确.  

        1>删除val的所有实例

        思路:遍历list,找到一个删一个.因为已定义了remove(Node* n),所以省事一些.

template<class T>
void list<T>::removeValue(const T& val){if(items==0){                                //空链表直接返回std::cout<<"链表内没有数据"<<std::endl;return;}list<T>::Node* p=first;                      //声明指针指向链表头结点bool flag=false;                             //声明标志位;     while(p){                                    //遍历链表if(p->t==val){remove(p);                           //调用删除结点函数flag=true;                           //标志位改变}p=p->next;                               //指针指向下一个结点}if(flag==true)std::cout<<"数据已全部删除"<<std::endl; elsestd::cout<<"链表内没有您想删除的数据"<<std::endl;  
}

          2>sort排序,从小到大排序,最小的放链表前面

           思路:要排序,我只知道冒泡排序,链表排序可以仿照冒泡排序算法吗?

            把链表"打散"成数组,然后给数组排序,接着把排好序后的结点重新找出来,依次挂到first后面.

             问题来了,现在的函数只能从结点访问到数据t,还没有从数据t访问到结点的函数,加一个呗    

template<class T>
Node* list<T>::findNode(const T& t){          //结点查找函数list<T>::Node * p=first;while(p){if(p->t==t)std::cout<<"您查找的数据已找到"<<std::endl;return p;p=p->next;                            //指向下一个结点}std::cout<<"您查找的数据不存在"<<std::endl;return nullptr;
}

         接下来按照冒泡排序的思路,把数据从小到大排列

template<class T>
void list<T>::sort(){                 //排序算法vector<T> a;List<T>::Node* p=first;while(p){a.push_back(p->t);            //元素取出来放进vector里p=p->next;                    //指针指向下一个结点}/*以下是冒泡排序*/for(int i=0;i<items-1;i++){for(int j=0;j<items-i-1;j++){if(a[j]>=a[j+1]){T tmp;tmp=a[j+1];a[j+1]=a[j];a[j]=tmp;}}}//到这里排序完成,从小到大,从a[0]到a[items-1]/*还原成结点,并依次挂到first后面*/Node* tmp=first;                   //声明临时结点tmp帮first整理,用上面的p也行for(int i=0;i<items;i++){
//两句说明结点后面是tmp->nextfindNode(a[i])->next=tmp->next;    tmp->next->front=findNode(a[i]);   
//两句说明结点前面是tmp;        tmp->next=findNode(a[i]); findNode(a[i])->front=tmp; 
//tmp结点指向新结点,为下次整理做准备;tmp=findNode(a[i]);        } last=tmp;                           //最后让last指向tmp;
}

        ----然而问题又来了,list并不检查两个相同的值,上面的findNode函数有bug该怎么办?想解决肯定是有办法的,比如给Node结点来个编号(题外话:黑皮书上有讲,那是本好书但是挺难)

    class Node{                       //声明结点类static int num;                   //静态变量,给对象编号用public:                           //结点数据向外部类公开int id;T t;Node *front;Node *next;Node(T val):t(val),front(0),next(0),id(num++){}Node():id(num++){}            //默认构造函数,为初始化时使用}

        但这样要耗费空间,查找结点代码也要改动,比较麻烦.所以我建议在排序之前先把多余的重复值去掉,也就是先调用下面要写的的unique()函数.

        ----除了这个问题还有个问题:让类型T的元素怎么比较?重载运算符吗?

/*???????????*/
bool operator<(T& t){    //起不了作用return *this < t
}

        如果从完全泛型的角度来讲,不可能成立.只能在调用时做出约束,如int,char,double等类型自带大小判断的才可以调用sort().

        如果对象中有部分元素是可以排序的,如有一个int属性,那么按照前面的思路,让其反向查找排序,这不是容器的事,应该在外面定义函数来解决.        

class Person{int age;        //这个可以排序string name;
}

        3>压缩链表,去掉多余元素

        思路:用一个集合a存储链表里的数据,遍历链表的同时,遍历集合a.当新元素在集合a里找到时,删除,当没有找到时,加入集合a.

template<class T>
void list<T>::unique(){              //将连续的相同元素压缩成单个元素list<T>::Node* p=first;vector<T> a;while(p){for(pt=a.begin();pt!=a.end();pt++){if(p->t==*pt){remove(p);           //调用删除结点函数}a.push_back(p->t);       //元素取出来放进vector里}p=p->next;                    //指针指向下一个结点}
}                  

        此外本书P699举了个例子,讲几种api的使用,看看即可.

链表梳理

        链表的定义和使用流程:数据→结点→链表.1.把数据放入结点;2.结点指针生成链表.

        链表是一个结点指针的集合,指针元素之间用结点指针相连接.头结点是链表的入口.

        链表的难点是区分指针变量和指针常量.

        链表里的元素是结点指针,他们是常量,要访问他们或者修改他们用的是指针变量.常见的指针变量有头结点,尾结点.他们时刻要保证逻辑正确,也是算法的保证. 

后记

        一天更了两篇,大热天还觉得挺兴奋.数据结构应该算是编程的分水岭,如果真的喜欢会享受代码和写作的过程.如果一时学不进去也挺难受,但也不要着急慢慢来,许多人也经历过那个过程.一起加油. 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C++ AVL树
  • 生活中生智慧
  • 《昇思25天学习打卡营第21天|Pix2Pix实现图像转换》
  • c++ extern 关键字
  • 提高自动化测试脚本编写效率 5大关键注意事项
  • 【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【22】【RabbitMQ】
  • Nacos 面试题及答案整理,最新面试题
  • maven项目打成可运行的jar及pom中的依赖一同打包
  • 持续集成01--Git版本管理及基础应用实践
  • Git学习记录
  • ES6 正则的扩展(十九)
  • 实战:详解Spring创建bean的流程(图解+示例+源码)
  • vscode搭建PyQt + Quick开发环境
  • 阿里云服务器 篇五:短链服务网站
  • 使用NIFI连接瀚高数据库_并从RestFul的HTTP接口中获取数据局_同步到瀚高数据库中---大数据之Nifi工作笔记0067
  • 【每日笔记】【Go学习笔记】2019-01-10 codis proxy处理流程
  • Angular 响应式表单 基础例子
  • es6--symbol
  • Iterator 和 for...of 循环
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • magento 货币换算
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • python3 使用 asyncio 代替线程
  • Travix是如何部署应用程序到Kubernetes上的
  • 初探 Vue 生命周期和钩子函数
  • 从0实现一个tiny react(三)生命周期
  • 关于for循环的简单归纳
  • 机器学习学习笔记一
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 浅谈Golang中select的用法
  • 学习使用ExpressJS 4.0中的新Router
  • 因为阿里,他们成了“杭漂”
  • 阿里云ACE认证之理解CDN技术
  • 通过调用文摘列表API获取文摘
  • ​TypeScript都不会用,也敢说会前端?
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • #Datawhale AI夏令营第4期#AIGC文生图方向复盘
  • #QT(串口助手-界面)
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (3)(3.5) 遥测无线电区域条例
  • (二开)Flink 修改源码拓展 SQL 语法
  • (二刷)代码随想录第16天|104.二叉树的最大深度 559.n叉树的最大深度● 111.二叉树的最小深度● 222.完全二叉树的节点个数
  • (附源码)spring boot公选课在线选课系统 毕业设计 142011
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (十二)python网络爬虫(理论+实战)——实战:使用BeautfulSoup解析baidu热搜新闻数据
  • (十一)手动添加用户和文件的特殊权限
  • (转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  • (转)一些感悟
  • (转载)利用webkit抓取动态网页和链接
  • .net core 调用c dll_用C++生成一个简单的DLL文件VS2008
  • .NET Standard、.NET Framework 、.NET Core三者的关系与区别?
  • .NET 将多个程序集合并成单一程序集的 4+3 种方法
  • .NET 使用配置文件
  • .NET技术成长路线架构图
  • :O)修改linux硬件时间