双向循环链表和它名字的表意一样,就是把双向链表的两头连接,使其成为了一个环状链表。只需要将表中最后一个节点的next指针指向头节点,头节点的prior指针指向尾节点,链表就能成环儿,如图所示:
需要注意的是,虽然双向循环链表成环状,但本质上还是双向链表,因此在双向循环链表中,依然能够找到头指针和头节点等。双向循环链表和双向链表相比,唯一的不同就是双向循环链表首尾相连,其他都完全一样。
注意:因为我上面已经讲了双向链表,所以这里只注重讲他们的实现差异。另因为带头节点会更好操作,所以我的代码都有头节点。
1、双向循环链表的创建
初始化时需要将头节点的next和prior都指向自己。

//1、初始化双向循环链表(带头节点)Status initLinkList(LinkList *list){//创建头节点list = malloc(sizeof(Node));if (list == NULL) {return ERROR;}//前驱和后继都指向自己(*list)->prior = list;(list)->data = -1;(*list)->next = *list;printf(“已初始化链表~\n”);return OK;}
讯享网

2、遍历双向循环链表
注意它的尾节点的next不再是Null,而是头节点
讯享网//2、遍历双向循环链表void printfLinkLisk(LinkList list){printf(“遍历链表:\n”);if (list == NULL || list->next == list) {printf(“这是一个空链表\n”);return;}LinkList p = list;//判断next是否全部正确printf(“根据next从前往后遍历:”);while (p->next != list) {printf(”%d “,p->next->data);p = p->next;}printf(”\n”);//判断prior是否全部正确printf(“根据prior从后往前遍历:”);while (p != list) {printf(”%d “,p->data);p = p->prior;}printf(”\n”);}
3、根据索引位置添加节点
这里不需要判断尾节点的next是否为Null,因为它会指向头节点。
//3、根据索引位置插入数据至链表中Status insertLinkList(LinkList *list, int index, ElemType data){if (list == NULL || index < 0) {return ERROR;}int i = 0;LinkList priorNode = *list;//判断插入的位置,这里开始位置是0,index超过链表长度则插入末尾while (i < index && priorNode->next != *list) {priorNode = priorNode->next;i++;}LinkList newNode = malloc(sizeof(Node));if (newNode == NULL) {return ERROR;}newNode->data = data;//插入操作共四步,看好了,别眨眼//1.将priorNode->next节点的前驱指向新节点priorNode->next->prior = newNode;//2.将新节点->next指向原来的priorNode->nextnewNode->next = priorNode->next;//3.将priorNode->next指向新节点priorNode->next = newNode;//4.新节点的前驱指向priorNodenewNode->prior = priorNode;return OK;}
4、根据索引位置删除节点
这里不需要判断尾节点的next是否为Null,因为它会指向头节点。
讯享网//4、根据索引位置删除节点Status deleteLinkListByIndex(LinkList *list, int index, ElemType data){if (list == NULL || index < 0) {return ERROR;}LinkList locaNode = *list;int i = 0;//注意别删了头节点while (i <= index) {locaNode = locaNode->next;if (locaNode == *list) {printf(“没有这个你想要删除的节点\n”);return ERROR;}i++;}//开始删除,只需要做两步locaNode->prior->next = locaNode->next;locaNode->next->prior = locaNode->prior;*data = locaNode->data;free(locaNode);return OK;}
5、根据存储的值删除节点
这里不需要判断尾节点的next是否为Null,因为它会指向头节点。
//5、根据存储的值删除节点Status deleteLinkListByData(LinkList list, ElemType data){if (list == NULL) {return ERROR;}LinkList locaNode = (*list)->next;while (locaNode != *list) {if (locaNode->data == data) {break;}locaNode = locaNode->next;}if (locaNode == *list) {printf(“没有这个你想要删除的节点\n”);return ERROR;}//开始删除,只需要做两步locaNode->prior->next = locaNode->next;locaNode->next->prior = locaNode->prior;free(locaNode);return OK;}

6、根据值查找节点
尾节点的next可是头节点哦,找到它就是最后一个了。
讯享网//6、查找元素Status selectNode(LinkList list, ElemType data, LinkList *locaNode){if (list == NULL) {return ERROR;}LinkList p = list->next;while (p != list) {if (p->data == data) {*locaNode = p;break;}p = p->next;}if (*locaNode == NULL) {printf(“没有这个你想要的节点\n”);return ERROR;}else {return OK;}}
其它代码
//元素类型typedef int ElemType;//状态类型typedef int Status;//定义节点结构体typedef struct Node {struct Node *prior;ElemType data;struct Node *next;} Node;typedef Node *LinkList;int main(int argc, const char * argv[]) {LinkList list;initLinkList(&list);for (int i = 0; i < 10; i ++) {insertLinkList(&list, i, i);}printfLinkLisk(list);int index, data;printf(“输入你想插入的位置(从0开始)和存储的值:”);scanf(”%d %d”,&index,&data);insertLinkList(&list, index, data);printfLinkLisk(list);printf(“输入你想删除的位置(从0开始):”);scanf(”%d”,&index);deleteLinkListByIndex(&list, index, &data);printfLinkLisk(list);printf(“输入你想删除的节点的值(只删最前的那个):”);scanf(”%d”,&data);deleteLinkListByData(&list, data);printfLinkLisk(list);printf(”\n”);return 0;}
输出结果:

*声明:本文于网络整理,版权归原作者所有,如来源信息有误或侵犯权益,请联系我们删除或授权事宜。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/168314.html