版权声明:转载请注明出处 https://blog.csdn.net/doubleguy/article/details/83622369
循环链表在单链表的基础上加入指向前驱的指针prior,其大致实现几乎和单链表一样,核心区别就是插入删除不同。
这里就着重围绕插入和删除来写,其他功能可以自己实现一下。如果双向链表不太懂的话,说明单链表你没弄得很明白,可以看下我的单链表弄明白:https://blog.csdn.net/doubleguy/article/details/83384327
1.创建双向链表(后插法)
//后插法创建双向链表
void CreateList(LinkList &l,int n){
l = new LNode;
l->next = NULL;
LNode *r = l;
for(int i=0;i<n;i++){
LNode *p = new LNode;
scanf("%d",&p->data);
p->prior = r;
r->next = p;
r = r->next;
p->next = NULL;
}
}
2.查找
这里注意一点,为了插入和删除的方便,我查找操作的返回值是指向要查找的位置的指针。举个例子,我调用GetElem(l,4)时,如果链表中有大于等于4位元素时它返回指向第4个元素位置的指针。它的好处可以在插入和删除中明显的看出来。
//查找
LNode *GetElem(LinkList l,int i){
LNode *p = l->next;
int j = 1;
while(j<i&&p){
p = p->next;
j++;
}
while(!p||i<j){
printf("输入越界!");
return NULL;
}
return p;
}
3.插入
直接调用GetElement()函数可以直接找到链表中第i个元素的位置指针,多方便啊!另外,这里的插入是在第i个位置前的一个元素插入。
//插入(在带头节点的双向链表l中第i个元素之前插入元素e)
Status ListInsert(LinkList &l,int i,int &e){
LNode *p = NULL;
if(!(p = GetElem(l,i)))
return 0;
LNode *r = new LNode;
r->data = e;
r->prior = p->prior;
p->prior->next = r;
r->next = p;
p->prior = r;
return 1;
}
4.删除
注意调用GetElement()函数时,指针p是指向第i个元素的,需要讨论一个p->next是否指向空,也即是讨论一下删除的元素是否是最后一位。
//删除带头节点的双向链表l的第i个位置的元素
Status ListDelete(LinkList &l,int i){
LNode *p = NULL;
if(!(p = GetElem(l,i)))
return 0;
if(p->next != NULL){
p->prior->next = p->next;
p->next->prior = p->prior;
}
else
p->prior->next = NULL;
delete p;
return 1;
}
完整代码如下:
#include<cstdio>
#include<algorithm>
#include<stdlib.h>
#pragma execution_character_set("utf-8")
typedef int Status;
using namespace std;
typedef struct LNode{
int data;
struct LNode *prior;
struct LNode *next;
}LNode,*LinkList;
Status InitList(LinkList &l){
l = new LNode;
return 1;
}
//后插法创建双向链表
void CreateList(LinkList &l,int n){
l = new LNode;
l->next = NULL;
LNode *r = l;
for(int i=0;i<n;i++){
LNode *p = new LNode;
scanf("%d",&p->data);
p->prior = r;
r->next = p;
r = r->next;
p->next = NULL;
}
}
//查找
LNode *GetElem(LinkList l,int i){
LNode *p = l->next;
int j = 1;
while(j<i&&p){
p = p->next;
j++;
}
while(!p||i<j){
printf("输入越界!");
return NULL;
}
return p;
}
//插入(在带头节点的双向链表l中第i个元素之前插入元素e)
Status ListInsert(LinkList &l,int i,int &e){
LNode *p = NULL;
if(!(p = GetElem(l,i)))
return 0;
LNode *r = new LNode;
r->data = e;
r->prior = p->prior;
p->prior->next = r;
r->next = p;
p->prior = r;
return 1;
}
//删除带头节点的双向链表l的第i个位置的元素
Status ListDelete(LinkList &l,int i){
LNode *p = NULL;
if(!(p = GetElem(l,i)))
return 0;
if(p->next != NULL){
p->prior->next = p->next;
p->next->prior = p->prior;
}
else
p->prior->next = NULL;
delete p;
return 1;
}
//打印函数
void PrintList(LinkList &l){
LNode *p = l->next;
if(!p){
printf("表为空!");
return;
}
while(p){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
int main(){
LinkList l;
int n;
int status;
int e,loc;
printf("请输入你想要创建的双向链表的长度n:");
scanf("%d",&n);
printf("请输入%d个数:",n);
CreateList(l,3);
printf("当前表中元素为:");
PrintList(l);
printf("请输入你要插入的位置和数值:");
scanf("%d%d",&loc,&e);
status = ListInsert(l,loc,e);
if(status){
printf("插入成功!\n当前表中元素为:");
PrintList(l);
}
else
printf("插入失败,输入越界!\n");
printf("请输入你要删除数的位置:");
scanf("%d",&loc);
status = ListDelete(l,loc);
if(status){
printf("删除成功!\n当前表中元素为:");
PrintList(l);
}
else
printf("删除失败,输入越界!\n");
return 0;
}