首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

【C语言教程】“双向循环链表”学习总结和C语言代码实现!

双向循环链表定义

双向循环链表和它名字的表意一样,就是把双向链表的两头连接,使其成为了一个环状链表。只需要将表中最后一个节点的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->next

  newNode->next = priorNode->next;

  //3.将priorNode->next指向新节点

  priorNode->next = newNode;

  //4.新节点的前驱指向priorNode

  newNode->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

      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;

  }

}

其它辅助代码

#include "stdlib.h"

#define OK    1

#define ERROR 0

//元素类型

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;

}

输出结果:

—END—

看到这里是不是又学到了很多新知识呢~

如果你很想学编程,C语言/C++编程学习基地

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200825A0EA3600?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券