数据结构第四篇——线性表的链式存储之双向链表
Posted T丶jl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构第四篇——线性表的链式存储之双向链表相关的知识,希望对你有一定的参考价值。
♥注:未经博主同意,不得转载。
前面讨论的单链表,每个结点中只有一个指针域,用来存放指向后继结点的指针,因此,从某个结点出发只能顺时针往后查找其他结点。若要查找某个结点的直接前驱,则需要从头指针开始沿链表探寻,处理起来十分不方便。为克服单链表的这一缺点,可引入双向链表。
双向链表中每一个结点含有两个指针域,一个指针指向其直接前驱结点,另一个指针指向直接后继结点。和单链表类似,双向链表一般也只有头指针唯一确定;同样也可设头结点,使得双向链表的某些操作简便一些。
双向链表结构定义如下:
双向链表是一种对称结构,和单链表相比,虽然每个结点增加了一个指针域,多占用了空间,但这给操作的实现带来了方便。
在双向链表中,若p为指向表中某一结点的指针,则显然有:
p->next->prior=p->prior->next=p
这个表达式恰当的反映了这种结构的特性。
在双向链表中,有些操作如取元素、求表长、定位等,只涉及一个方向的指针,则这些操作的算法描述和单链表相同。但在进行插入、删除操作时有很大的不同,在双向链表中需同时修改两个方向上的指针,还要小心修改顺序。
1.结点删除操作:
删除结点p时,先从头结点开始搜索链表,找到p后做以下操作:
p->prior->next=p->next;
if(p->next)
p->next->prior=p->prior;
整个完整删除函数为:
1 //删除操作 2 Data DBList::Delete(int i) 3 { 4 DNode* p = head; 5 int k=0; 6 while(p&&k<i-1) //将p指到要删除的位置 7 { 8 p=p->next; 9 ++k; 10 } 11 if(!p||p->next==NULL) //判断删除位置是否存在和是否有后继 12 { 13 cout<<"删除位置非法"<<endl; 14 exit(0); 15 } 16 DNode* q = p->next; //暂存删除结点 17 18 p->prior->next=p->next; 19 if(!p->next) 20 p->next->prior=p->prior; 21 22 Data e=q->data; //将删除的元素储存起来 23 delete q; //释放将要删除的结点 24 return e; 25 }
2.结点插入操作:
在结点p之前插入结点s,先从头结点开始搜索链表,找到p后做以下操作:
s = new DNode; //创建此结点
s->data=e; //将元素存入创建的结点
s->prior=p->prior;
p->prior->next=s;
p->prior=s;
s->next=p;
整个完整插入函数为:
1 //插入操作 2 void DBList::Insert(Data x,int i) 3 { 4 DNode* p=head; 5 int k=0; 6 while(p&&k<i-1) // 将p指到第i个位置 7 { 8 p=p->next; 9 ++k; 10 } 11 if(!p||k>i-1) //判断是否存在第i个元素 12 { 13 cout<<"第"<<i<<"个元素不存在"<<endl; 14 exit(0); 15 } 16 DNode* s = new DNode; //创建此结点 17 if(!s) 18 { 19 cout<<"空间分配失败"<<endl; 20 exit(0); 21 } 22 23 s->data=x; //将元素存入创建的结点 24 s->prior=p->prior; 25 p->prior->next=s; 26 p->prior=s; 27 s->next=p; 28 }
3.创建双向链表:
1 typedef int Data; 2 3 struct DNode 4 { 5 Data data; //数据 6 DNode* prior; //指向前驱的指针 7 DNode* next; //指向后继的指针 8 }; 9 10 class DBList 11 { 12 DNode* head; //创建头结点 13 public: 14 DBList() //构造函数 15 { 16 head = new DNode; 17 head->next = NULL; 18 head->prior = NULL; 19 } 20 ~DBList(); //析构函数 21 22 Data GetElem(int i); //取第i个元素的值 23 bool IsEmpty(); //判断是否为空链表 24 void Create(Data* a , int n); //创建长度为n的双链表(头插法) 25 void Create1(Data* a , int n); //创建长度为n的双链表(尾插法) 26 DNode* Locate(Data e,int* i); //查找值为e的结点,返回指向e的指针 27 28 DNode* Prior(Data e); //返回元素e的前驱 29 DNode* Prior1(int i); //返回第i个元素的前驱 30 DNode* Next(Data e); //返回元素e的后继 31 DNode* Next1(int i); //返回第i个元素的后继 32 33 void Insert(Data x,int i); //将数据元素x插入到第i个位置 34 Data Delete(int i); //删除第i个元素 35 //int _Delete(Data e); //删除值为e的第一个元素 36 int Size(); //返回链表的长度 37 void Clear(); //清空 38 void Print(); //正向显示元素 39 void Print1(); //逆向显示元素 40 };
这里是其他部分函数的实现:
1 //计算链表长度 2 int DBList::Size() 3 { 4 DNode* 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 DBList::Print() 18 { 19 DNode* 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 void DBList::Print1() 31 { 32 DNode* p; //创建指针p 33 p=head->next; //p指向第一个元素结点 34 while(p) 35 { 36 if(p->next) 37 p=p->next; 38 else 39 break; 40 } 41 42 while(p) 43 { 44 cout<<p->data<<" "; 45 p=p->prior; 46 } 47 cout<<endl; 48 } 49 50 51 //取元素 52 Data DBList::GetElem(int i) 53 { 54 if(head->next == NULL) //为空链表 55 { 56 cout<<"此链表为空"<<endl; 57 exit(0); 58 } 59 else 60 { 61 DNode* p; //创建指针p 62 int k; 63 p=head; //p指向头结点 64 k=0; 65 while(p&&k<i) //p移到i的位置 66 { 67 p=p->next; 68 k++; 69 } 70 if(!p||k>i) //超出个数范围 71 { 72 cout<<"第"<<i<<"个元素不存在"<<endl; 73 exit(0); 74 } 75 return (p->data); 76 } 77 } //此算法的时间复杂度为O(n) 78 79 //判断链表是否为空 80 bool DBList::IsEmpty() 81 { 82 if(head->next==NULL) 83 { 84 cout<<"此链表为空"<<endl; 85 return true; 86 } 87 else 88 { 89 cout<<"此链表非空"<<endl; 90 return false; 91 } 92 } 93 94 //建立双链表 95 //第一种是头插法 96 void DBList::Create(Data* a,int n) 97 { 98 DNode* p=NULL; 99 DNode* q=head; 100 for(int i=n-1;i>=0;--i) 101 { 102 p=new DNode; //创建新结点 103 p->data=a[i]; //将元素存入结点 104 105 q=p->prior; 106 p->next=head->next; //将新加入结点指向头结点后面 107 head->next=p; //将头结点指向新加入的结点 108 q=p; 109 } 110 } 111 112 //查找给定值的结点 113 DNode* DBList::Locate(Data e,int *i) 114 { 115 *i=1; 116 DNode* p=NULL; 117 p=head->next; 118 while(p) //p不为空 119 { 120 if(p->data==e) //找到元素 121 return p; 122 else 123 { 124 p=p->next; 125 ++(*i); 126 } 127 } 128 cout<<"当前链表中无此元素"<<endl; 129 exit(0); 130 return NULL; 131 } 132 133 //清空双链表 134 //保留表头结点,把双链表中的 135 //其余所有结点全部释放。 136 void DBList::Clear() 137 { 138 DNode* p=NULL; 139 DNode* q=NULL; 140 p=head->next; 141 while(p) 142 { 143 q=p; 144 p=p->next; 145 delete q; 146 } 147 head->next = NULL; 148 head->prior = NULL; 149 } 150 151 //析构函数 152 //释放双链表中的所有元素。 153 DBList::~DBList() 154 { 155 DNode* p; 156 p=head; 157 while(p) 158 { 159 p=p->next; 160 delete head; 161 head=p; 162 } 163 }
其他操作请参考上篇文章的部分内容:http://www.cnblogs.com/tenjl-exv/p/7470075.html
本次内容到这里就结束了。
v、
以上是关于数据结构第四篇——线性表的链式存储之双向链表的主要内容,如果未能解决你的问题,请参考以下文章