数据结构与算法之----线性表
2015-03-17 11:16
155 查看
1、线性表的顺序存储结构
1.1 顺序表的创建和遍历
#include "stdafx.h" #include<iostream> #include<string.h> using namespace std; struct Sqlist { int *data; int length; int maxsize; Sqlist():length(0){} }; void ListInsert(Sqlist &L,int i,int e) { if(L.length==L.maxsize ||(i<0||i>L.length))//判断是否已满 或者i不在范围之内,但是要考虑到在末尾插入的情况 { cout<<"out of range"<<endl; return; } for(int a=L.length;a>i;a--) { L.data[a]=L.data[a-1]; } L.data[a]=e; L.length++; } void PrintList(Sqlist &L) { for(int i=0;i<L.length;i++) { cout<<L.data[i]; } cout<<'\n'; } int _tmain(int argc, _TCHAR* argv[]) { Sqlist L; cout<<"请输入顺序表长度"<<endl; cin>>L.maxsize; L.data=new int[L.maxsize](); for(int i=0;i<5;i++) { int e; cin>>e; ListInsert(L,i,e); } PrintList(L); }输出:
请输入顺序表长度
10
8 7 6 5 4
87654
Press any key to continue
思想:
(1)注意在插入的时候,位置的选择,只能是在[0,length]上,否则会造成空隙,不好操作。
(2)这种游标方式,比书上的看起来更加方便,从尾部开始,用前面的值覆盖后面的值
(3)要注意判断是否满了的情况
(4)插入之后length++
1.2顺序表的删除
void DeleteList(Sqlist &L,int i,int &e) { if(i<0 || i>=L.length) { cout<<"out of range"<<endl; return; } else { e=L.data[i]; for(int a=i;a<L.length-1;a++) L.data[a]=L.data[a+1]; L.length--; //千万不要忘了使 length-1,否则会出问题,因为原来数组末尾中的元素是没有删除的 } }思想:
(1)千万不要忘记length--
(2)从i开始,利用后面的值覆盖前面的值
2、线性表的链式存储结构
2.1、线性表的整表创建、遍历、整表删除
#include "stdafx.h" #include<iostream> #include<string.h> using namespace std; struct Node { int data; Node *next; Node():next(NULL),data(0){} }; void CreateList(Node *L)//整表创建 { int a; while(1)//不要忘了这个1,这里的插入法无需用递归,因为不需要子操作就能完成 { cin>>a; if(a==8)return; Node *p=new Node();//前插法 p->data=a; p->next=L->next; L->next=p; } } void PrintList(const Node *L) { Node *p=L->next;//指向第一个 while(p) { cout<<p->data; p=p->next; } cout<<'\n'; } void EmptyList(Node *L) { if(L->next)EmptyList(L->next); cout<<L->data; delete L; } int _tmain(int argc, _TCHAR* argv[]) { Node *L=new Node(); CreateList(L); PrintList(L); EmptyList(L); return 0; }
输出:
3 7 6 5 4 8
45673
376540Press any key to continue
思想:
(1)首先要创建表头,为了跟后面节点风格统一,头结点也用new来创建,那么整个链表就都可以用指针来传递,方便后面的删除递归操作。
(2)整表创建,这里可以用前插,或者后插法,利用while(1)循环来控制插入个数
(3)整表遍历,同样用while(not null),遍历链表即可。
(4)整表删除,用递归的方式,递归体为,若还有子节点,那么先删除子节点,再删除自己,注意这个是并列的操作,是一起完成的。递归出口,显然就是没有子节点了。
(5)while(p)和while(p->next)的区别是 前者最后p指向的是空的,而对于后者,指向的是最后一个元素。所以后者对于插入而言是不错的
2.2、链表的插入、删除操作
插入void ListInsert(Node *L,int i,int e) { Node *p=L; int j=0; while(j<i && p->next!=NULL)//同样要考虑在第0个和最后一个后面插入的情况,因此,指针指向插入前的位置 { p=p->next; j++; } if(j==i)//若i在长度范围内,那么执行插入操作,这里的j相当于一个计数器,而且是在链表长度范围内的,因为有P的判断控制 { Node *node=new Node; node->data=e; node->next=p->next; p->next=node; } else cout<<"out of range"<<endl; }思想:
(1)对于链表的操作,进行遍历的时候,一定要用另外一个指针来遍历,也就是说,不要改变原来指针的位置。
(2)while的判断,一般要判断其下一个是否为空,所以用p-next进行判断最好,即进行了判断,而且指针最后停在了有值的位置。不会溢出
删除
void ListDelete(Node *L,int i) { Node *p=L; int j=0; while(j<i && p->next!=NULL) { p=p->next; j++; } if(j==i && p->next!=NULL)//这个就是和插入 遍历之后的一点小区别,因为插入可以在最末尾,空的位置插入,但是不能删除空的位置 { Node *node=p->next; p->next=node->next; delete node; } else cout<<"out of range"<<endl; }
输出:
3 7 6 5 4 8
45673
删除之后为
4573
37540Press any key to continue
思想:
(1)遍历方式和插入完全一样,都需要找到插入位置的前一个
(2)删除操作唯一不同的时候,是需要先判断定位的下一个是否是空的,为空的话是不需要删除的,否则会出问题,而对于插入,当是空的时候是可以插入的。
3、循环链表
要将一个链表编程循环链表,可以这么做:(1)存储头指针
(2)遍历链表,指向队尾,将尾部的next指向头指针,返回队尾,下次访问的时候,第一个就是访问尾部,通过尾部,也可以访问头指针,形成了循环链表
(3)这种结构的好处就是,可以轻松将两个这样的循环链表连接成一个循环链表,只需要做一些简单的指针修改即可,不需要再遍历一个链表。
4、双向链表
(1)就是设置两个指针地域,一个指向前驱prior 一个指向next(2)头指针的前驱为尾指针,尾指针的后继为前指针
(3)这样就形成了双向链表。
(4)有时间要尝试构造下,应该不难
相关文章推荐
- 数据结构 线性表算法的实现
- 线性表2 - 数据结构和算法07
- 一步一步复习数据结构和算法基础-线性表
- 遗世蒹葭~小甲鱼~数据结构和算法_02~线性表
- 数据结构和算法学习 -- 线性表
- 数据结构与算法——线性表顺序存储结构
- 算法与数据结构--在顺序线性表L中查找第1个值与e满足compare()的元素的为序--算法2.5
- 线性表13|约瑟夫问题 – 数据结构和算法18
- 线性表12|循环链表 - 数据结构和算法17
- 数据结构与算法——线性表 1
- 数据结构与算法——线性表链式存储结构(静态链表)
- 线性表12|循环链表 - 数据结构和算法17
- 应用数据结构(一)线性表节点的插入和删除算法
- 数据结构和算法笔记 lesson4 线性表链式存储结构 单链表
- 数据结构与算法——线性表链式存储(双向循环链表)
- 【算法和数据结构】线性表(三)栈的定义和封装
- 线性表15|魔术师发牌问题和拉丁方阵 - 数据结构和算法20
- 学好数据结构和算法 —— 线性表
- 【算法和数据结构】线性表(一)线性表(C++实现)
- 脚踏实地-算法与数据结构-线性表