循环双链表:
与单链表相比,双链表的优势就是可以双向操作链表,在单链表中只能从表头节点开始往后顺序遍历整个链表,而循环双链表可以从表中任意节点遍历。其缺点就是 由于一个不仅有头指针,而且存在尾指针,相比于单链表来说就比较浪费存储空间。
循环双链表代码实现:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
typedef struct DNode{
int data;
struct DNode *prior,*next;
}DNode,*DLinkList;
//头插法建立双链表
DLinkList Head_List(DLinkList &D){
D =(DLinkList)malloc(sizeof(DNode));//头节点
D->next=NULL;//空链表初始化,首尾指针都置为空
D->prior=NULL;
DNode *s;//用于指向新节点的指针
int x;
printf("请输入数据,输入9999代表结束\n");
scanf("%d",&x);
while(x!=9999){
s=(DNode*)malloc(sizeof(DNode));
s->data=x;
s->prior=D->prior;
D->prior=s;
s->next=D->next;
D->next=s;
scanf("%d",&x);
}
return D;
}
//获取链表长度
int getLength(DLinkList D){
DNode *d;
d=D;
int length=0;
while(d->next!=NULL){
d=d->next;
length++;
}
return length;
}
void PrintDLinkList(DLinkList D){
DNode *d=D,*p;
int a=getLength(D);
printf("┌");
//根据链表长度调整横线长度
//可根据需要调整输出格式
for(int i=0;i<a;i++){
printf("----");
}
printf(" ↘\n");
printf("head<=>");
while(d->next != NULL){
d=d->next;
if(d->next!=NULL){
printf("%d<=>",d->data);
}else if(d->next==NULL){
printf("%d",d->data);
}
}
printf("\n");
if(d->next==NULL){
printf(" ↖");
for(int i=0;i<a;i++){
printf("----");
}
printf("┘\n");
}
}
DNode* GetElem(DLinkList D,int i){
int j =1;
DNode *p=D->next;
if(i==0)
return D; //若i等于0,则返回头节点
if(i<1)
return NULL;//若i无效,则返回头节点
while(p&&j<i){
p=p->next;
j++;
}
return p;
}
void Insert_List(DLinkList &D,int i,int e){
DNode *p=GetElem(D,i-1);//获取插入位置的前一节点
DNode *d=(DNode*)malloc(sizeof(DNode));//为新插入的节点分配空间
d->data=e;
d->next=p->next;//先成链
d->prior=p;
p->next->prior=d;//再断链
p->next=d;
}
void Delete_List(DLinkList &D,int i){
DNode *p =GetElem(D,i-1);
DNode *q=GetElem(D,i);
p->next=q->next;
q->next->prior=p;
free(q);
}
int main(){
DLinkList d;
Head_List(d);
PrintDLinkList(d);
printf("单链表表长为%d\n",getLength(d));
Insert_List(d,2,9999);
PrintDLinkList(d);
printf("单链表表长为%d\n",getLength(d));
Delete_List(d,2);
PrintDLinkList(d);
printf("单链表表长为%d\n",getLength(d));
}
运行效果截图: