数据结构第三篇——线性表的链式存储之单链表
♥注:未经博主同意,不得转载。
线性表的链式存储结构的特点是用一组任意的存储单元来存储线性表的数据元素,这些单元可以分散在内存中的任意位置上,其在物理上可以是连续的,也可以是不连续的。具有链式存储结构的线性表称为线性链表。
为了表示出每个数据元素与其后继之间的关系,除了存储数据元素本身的信息之外,还需存储指示其直接后继的信息。这可以用一个结点(node)来完整的表示。
将节点中存储数据元素本身信息的域称为数据域;存储其直接后继位置的域称为指针域。指针域中存储的信息称作指针或链。
一般情况下,链表中每个结点可以包含若干个数据域和若干个指针域。如果每个结点中只包含一个指针域,则称其为单链表。
为了便于实现各种操作,可以在单链表的第一个结点之前增设一个结点,称为头结点,其他结点称为表结点。
带头结点的单链表描述如下:
1 typedef int Data; 2 3 struct Node 4 { 5 Data data; //数据 6 Node* next; //指针 7 }; 8 9 class LinkList 10 { 11 Node* head; //创建头结点 12 public: 13 LinkList() //构造函数 14 { 15 head = new Node; 16 head->next = NULL; 17 } 18 ~LinkList(); //析构函数 19 Data GetElem(int i); //取第i个元素的值 20 bool IsEmpty(); //判断是否为空链表 21 void Create(Data* a , int n); //创建长度为n的单链表(头插法) 22 void Create1(Data* a , int n); //创建长度为n的单链表(尾插法) 23 Node* Locate(Data e,int* i); //查找值为e的结点,返回指向e的指针 24 void Insert(Data x,int i); //将数据元素x插入到第i个位置 25 Data Delete(int i); //删除第i个元素 26 //int _Delete(Data e); //删除值为e的第一个元素 27 int Size(); //返回链表的长度 28 void Clear(); //清空 29 void Print(); //显示元素 30 }; 31
下面则是这些操作在单链表上的实现:
1 //计算链表长度 2 int LinkList::Size() 3 { 4 Node* p; //创建指针p 5 int k; 6 p=head->next; ////p指向第一个元素结点 7 k=0; 8 while(p) 9 { 10 p=p->next; 11 ++k; 12 } 13 return k; 14 } 15 16 //显示所有元素 17 void LinkList::Print() 18 { 19 Node* p; //创建指针p 20 p=head->next; ////p指向第一个元素结点 21 while(p) 22 { 23 cout<<p->data<<" "; 24 p=p->next; 25 } 26 cout<<endl; 27 } 28 29 //取元素 30 Data LinkList::GetElem(int i) 31 { 32 if(head->next == NULL) //为空链表 33 { 34 cout<<"此链表为空"<<endl; 35 exit(0); 36 } 37 else 38 { 39 Node* p; //创建指针p 40 int k; 41 p=head; //p指向头结点 42 k=0; 43 while(p&&k<i) //p移到i的位置 44 { 45 p=p->next; 46 k++; 47 } 48 if(!p||k>i) //超出个数范围 49 { 50 cout<<"第"<<i<<"个元素不存在"<<endl; 51 exit(0); 52 } 53 return (p->data); 54 } 55 } //此算法的时间复杂度为O(n) 56 57 //插入操作 58 void LinkList::Insert(Data x,int i) 59 { 60 Node* p=head; 61 int k=0; 62 while(p&&k<i-1) // 将p指到第i个位置 63 { 64 p=p->next; 65 ++k; 66 } 67 if(!p||k>i-1) //判断是否存在第i个元素 68 { 69 cout<<"第"<<i<<"个元素不存在"<<endl; 70 exit(0); 71 } 72 Node* s = new Node; //创建此结点 73 if(!s) 74 { 75 cout<<"空间分配失败"<<endl; 76 exit(0); 77 } 78 s->data=x; //将元素存入创建的结点 79 s->next=p->next; 80 p->next=s; 81 } 82 83 //删除操作 84 Data LinkList::Delete(int i) 85 { 86 Node* p = head; 87 int k=0; 88 while(p&&k<i-1) //将p指到要删除的位置 89 { 90 p=p->next; 91 ++k; 92 } 93 if(!p||p->next==NULL) //判断删除位置是否存在和是否有后继 94 { 95 cout<<"删除位置非法"<<endl; 96 exit(0); 97 } 98 Node* q = p->next; //暂存删除结点 99 p->next = q->next; //将结点隔离出来 100 Data e=q->data; //将删除的元素储存起来 101 delete q; //释放将要删除的结点 102 return e; 103 } 104 105 bool LinkList::IsEmpty() 106 { 107 if(head->next==NULL) 108 { 109 cout<<"此链表为空"<<endl; 110 return true; 111 } 112 else 113 { 114 cout<<"此链表非空"<<endl; 115 return false; 116 } 117 } 118 119 //建立单链表 120 //第一种是头插法 121 void LinkList::Create(Data* a,int n) 122 { 123 Node* p=NULL; 124 Node* q=NULL; 125 for(int i=n-1;i>=0;--i) 126 { 127 p=new Node; //创建新结点 128 p->data=a[i]; //将元素存入结点 129 p->next=head->next; //将新加入结点指向头结点后面 130 head->next=p; //将头结点指向新加入的结点 131 } 132 } 133 134 //第二种是尾插法 135 void LinkList::Create1(Data* a,int n) 136 { 137 Node* p=NULL; 138 Node* q=head; //创建中间结点指针 139 for(int i=0;i<n;++i) 140 { 141 p=new Node; //创建储存元素的新结点 142 p->data=a[i]; //将元素存入创建的结点 143 p->next=q->next; //插入到终端结点之后 144 q->next=p; //终端结点指向新建结点 145 q=p; //q指向新建结点 146 } 147 p->next=NULL; 148 } 149 150 //查找给定值的结点 151 Node* LinkList::Locate(Data e,int *i) 152 { 153 *i=1; 154 Node* p=NULL; 155 p=head->next; 156 while(p) //p不为空 157 { 158 if(p->data==e) //找到元素 159 return p; 160 else 161 { 162 p=p->next; 163 ++(*i); 164 } 165 } 166 cout<<"当前链表中无此元素"<<endl; 167 exit(0); 168 return NULL; 169 } 170 171 //清空单链表 172 //保留表头结点,把单链表中的 173 //其余所有结点全部释放。 174 void LinkList::Clear() 175 { 176 Node* p=NULL; 177 Node* q=NULL; 178 p=head->next; 179 while(p) 180 { 181 q=p; 182 p=p->next; 183 delete q; 184 } 185 head->next = NULL; 186 } 187 188 //析构函数 189 //释放单链表中的所有元素。 190 LinkList::~LinkList() 191 { 192 Node* p; 193 p=head; 194 while(p) 195 { 196 p=p->next; 197 delete head; 198 head=p; 199 } 200 }
需要注意的几点:
1.在创建链表时有两种创建方法,即头插法和尾插法,具体怎么实现请看下图:
2.在创建终结点(即屁股结点)时要注意指向下一个结点的指针要进行处理:p->next=NULL;
3,在用完链表后要记得进行销毁(释放内存),可以在析构函数中完成。
最后则是函数的测试,放在main函数里:
1 int main() 2 { 3 int i=0; 4 Data e; 5 int a[8]={2,4,6,8,5,1,7,9}; 6 7 LinkList list; //创建链表类 8 list.IsEmpty(); //判断链表是否为空 9 list.Create(a,8); //将数据插入 10 list.Print(); //显示 11 cout<<"链表长度:"<<list.Size()<<endl; 12 13 cout<<"输入要插入的元素和位置:"; 14 cin>>e>>i; 15 list.Insert(e,i); //插入数据 16 list.Print(); 17 cout<<"当前链表长度为"<<list.Size()<<endl<<endl; 18 19 cout<<"输入要插入的元素和位置:"; 20 cin>>e>>i; 21 list.Insert(e,i); 22 list.Print(); 23 cout<<"当前链表长度为"<<list.Size()<<endl<<endl; 24 25 cout<<"输入要插入的元素和位置:"; 26 cin>>e>>i; 27 list.Insert(e,i); 28 list.Print(); 29 cout<<"当前链表长度为"<<list.Size()<<endl<<endl; 30 31 cout<<"输入要查找的元素值:"; 32 cin>>e; 33 list.Locate(e,&i); //查找某元素 34 cout<<"这是第"<<i<<"个元素"<<endl<<endl; 35 36 cout<<"输入要查找的元素值:"; 37 cin>>e; 38 list.Locate(e,&i); 39 cout<<"这是第"<<i<<"个元素"<<endl<<endl; 40 41 list.IsEmpty(); //判断链表是否为空 42 43 cout<<"输入要查找的元素位置:"; 44 cin>>i; 45 e=list.GetElem(i); //查找第i个位置的元素 46 cout<<"这个元素值为:"<<e<<endl<<endl; 47 48 cout<<"输入要查找的元素位置:"; 49 cin>>i; 50 e=list.GetElem(i); //查找第i个位置的元素 51 cout<<"这个元素值为:"<<e<<endl<<endl; 52 53 list.IsEmpty(); //判断链表是否为空 54 55 cout<<"输入要删除的元素位置:"; 56 cin>>i; 57 e=list.Delete(i); //删除第i个位置的元素 58 cout<<"这个元素值为:"<<e<<endl; 59 list.Print(); 60 cout<<"当前链表长度为"<<list.Size()<<endl<<endl; 61 62 cout<<"输入要删除的元素位置:"; 63 cin>>i; 64 e=list.Delete(i); //删除第i个位置的元素 65 cout<<"这个元素值为:"<<e<<endl; 66 list.Print(); 67 cout<<"当前链表长度为"<<list.Size()<<endl<<endl; 68 69 list.Clear(); 70 list.IsEmpty(); //判断链表是否为空 71 72 return 0; 73 }
最后则是程序运行后的画面了:
到这里线性表链式存储中的单链表就结束了,下次内容则是双链表的实现。
转载于:https://www.cnblogs.com/tenjl-exv/p/7470075.html
数据结构第三篇——线性表的链式存储之单链表相关推荐
- 从零开始学数据结构和算法(二)线性表的链式存储结构
链表 链式存储结构 定义 线性表的链式存储结构的特点是用一组任意的存储单元的存储线性表的数据元素,这组存储单元是可以连续的,也可以是不连续的. 种类 结构图 单链表 应用:MessageQueue 插 ...
- 数据结构开发(5):线性表的链式存储结构
0.目录 1.线性表的链式存储结构 2.单链表的具体实现 3.顺序表和单链表的对比分析 4.小结 1.线性表的链式存储结构 顺序存储结构线性表的最大问题是: 插入和删除需要移动大量的元素!如何解决? ...
- 数据结构(四)—— 线性表的链式存储
线性表的链式存储 目录 1.链式存储结构与顺序存储结构的比较 2.单链表.双链表与循环链表 3.单链表的实现 1.链式存储结构与顺序存储结构的比较 顺序存储的特点:已物理相邻表示逻辑关系,任一元素均可 ...
- 严蔚敏数据结构C语言版——线性表的链式存储方式详细代码
一.严蔚敏数据结构C语言版 由于书上的许多地方都是伪代码,所以下面的代码对课本上的做了一些改动,使代码能够正常运行 链表的定义即相关类型定义 typedef int ElementType; type ...
- 【数据结构】线性表的链式表示-循环单链表、循环双链表、静态链表
循环单链表 从任何一个结点出发都能访问到链表的每一个元素 判空条件不是头节点的后继指针是否为空,而是它是否等于头指针 有时对单链表常做的操作实在表头和表尾进行的,此时可对循环单链表不设头指针而仅设尾指 ...
- C语言 线性表的链式存储结构(链表实现)
描述 主题:链表 功能:分别实链表的插入.删除.查找操作 提示:如果需要进入下一步操作,输入3个ctrl z即可 代码 //主题:链表 //功能:分别实链表的插入.删除.查找操作 //提示:如果需要进 ...
- 【数据结构】线性表的链式存储-单链表
单链表的定义 线性表的链式存储又称为单链表,它是指通过一组任意的存储单元来存储线性表中的数据元素. 为了建立起数据元素之间的线性关系,对每个链表结点,除了存放元素自身的信息之外,还需要存放一个指向其后 ...
- 线性表的链式存储结构及代码实现(单链表,双链表,循环链表)
在上一篇博文中介绍了线性表的顺序存储方式,它最大的缺点就是在插入和删除操作时会移动大量的元素,这显然会耗费很多时间.后来人们便想到了用链式存储方式来解决上面这一问题.链式存储线性表时,不需要使用地 ...
- 单链表(线性表的链式存储)---C语言版
目录 单链表(线性表的链式存储)---C语言版 一.相关说明 二.单链表的定义 三.单链表上具体操作的实现和时间复杂度 1.初始化表.构造一个空表. 2.根据数组创建单链表 3.求表长 4.插入操作. ...
最新文章
- Play Framework 2.5 整合 MyBatis
- 让Jexus支持高并发请求的优化技巧
- 听说过OpenJDK,没说过OpenValueJDK吧?
- python教程timeit模块的使用教程
- 省呱呱典型用户和用户场景
- boost::spirit模块实现从一个包含键/值对的容器中生成输出的测试程序
- 中国农业科学院(深圳)农业基因组所Yuwen Liu课题组诚聘副研究员(30-50万)
- 科研项目 | 深度参与前沿课题研究,全英华人教授协会(ABCP)资深学者亲授
- [转载] python中三角函数_Python中的三角函数
- 航海王启航服务器维护要多久,《航海王启航》7月1日服务器更新维护公告
- 2011年春月游溧阳有感
- 安装Microsoft Office - Win系统
- android用代码返回桌面
- 电机控制器功率电路MOS管及驱动芯片选型若干问题总结
- 四象限工作法:四象限时间管理法则及四象限工作法软件
- 成功的人生需要准确的定位
- python 网格交易源码_Python版简单网格策略
- 【中秋征文】手把手教你海面月亮升起中秋节特效制作
- win10+ubuntu 18.04双系统(联想小新13pro)——我终于安好了!
- 怎么免费把pdf转换成jpg图片
热门文章
- java打印等腰三角形_可打印丨四年级数学易错易失分的26个知识点总结(附例题+答案),给孩子收藏!...
- android快速开发框架_【程序源代码】springboot和ssm的极速轻量快速开发框架
- vue props 多类型_一个TypeScript简例,以及Vue支持TS的一些些事儿
- 将mysql数据库中的图片读出来的_MySQL存入图片+Qt读入读出数据库中的图片
- oracle表还原truncate,Oracle数据库执行truncate table操作后如何逆向恢复之前的状态...
- ercharts一个页面能放几个_Django的页面模版提取(三)
- EZEMC测试软件_四种常见的EMC仿真软件介绍
- 练习题︱ python 协同过滤ALS模型实现:商品推荐 + 用户人群放大
- [Flink]Flink的window介绍
- 利用YQL制作自己的小工具