【循环链表】数据结构——单向循环链表和双向循环链表操作&笔记

简介: 【循环链表】数据结构——单向循环链表和双向循环链表操作&笔记

一、单向循环链表

将单链表的首尾节点相连就形成了单向循环链表。

1、单向循环链表的节点

2、单向循环链表的结构

单向循环链表只有一个节点时:

二、双向循环链表

1、双向循环链表示意图

2、双向循环链表节点设计

struct d_node{
  int data; //数据域
  struct d_node *next;
  struct d_node *prev;
};

3、双向循环链表的一般性结构

1)只有头结点的情况

2)有多个节点的情况

4、双向循环链表头插法插入节点

步骤:

1)p->next = head->next

2)head->next = p;

3)p->next->prev = p;

4)p->prev = head;

若双向循环链表只有一个节点

步骤:

1)head->next = p;

2)p->prev = head;

5、双向循环链表尾插法

步骤:

1)处理前继指针

p->prev = head->prev;

head->prev = p;

2)处理后继指针

p->prev->next = p;

p->next = head;

6、双向循环链表节点的删除

删除指定节点p步骤:

1)从逻辑上在链表中把p节点删除

p->prev->next = p->next;

p->next->prev = p->prev;

2)从物理上删除节点p——free§

若p节点是链表的最后一个节点,那就:p->prev->next = NULL;

示例代码

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

//0,设计双向循环链表节点
typedef struct d_node{
  int data;
  struct d_node *prev;  //前继指针
  struct d_node *next;  //后继指针
}D_NODE;

//1,创建双向循环链表
D_NODE *D_Loop_List_Create(void)
{
  //1)申请链表头结点堆空间
  D_NODE *d_list = (D_NODE *)malloc(sizeof(D_NODE));
  if (NULL == d_list)
  {
    perror("malloc failed");
    return NULL;
  }
  //2)对头结点进行赋值
  d_list->prev = d_list;
  d_list->next = d_list;

  //3)返回头结点地址
  return d_list;
}

//2,添加链表节点 -->头插法
bool D_Loop_List_Insert_Head(D_NODE *head, int data)
{
  //1,新节点申请堆空间
  D_NODE *newnode = (D_NODE *)malloc(sizeof(D_NODE));
  if (NULL == newnode)
  {
    perror("malloc newnode failed");
    return false;
  }
  //2,对新节点进行赋值
  newnode->data = data;
  newnode->prev = newnode;
  newnode->next = newnode;

  //3,头插法插入链表
  newnode->next = head->next;
  head->next = newnode;

  newnode->next->prev = newnode;
  newnode->prev = head;
  return true;
}
//尾插法
bool D_Loop_List_Insert_End(D_NODE *head, int data)
{
  //1,新节点申请堆空间
  D_NODE *newnode = (D_NODE *)malloc(sizeof(D_NODE));
  if (NULL == newnode)
  {
    perror("malloc newnode failed");
    return false;
  }
  //2,对新节点进行赋值
  newnode->data = data;
  newnode->prev = newnode;
  newnode->next = newnode;

  //尾插法插入节点
    //1)处理前继指针
    newnode->prev = head->prev;
    head->prev = newnode;
    //2)处理后继指针
    newnode->prev->next = newnode;
    newnode->next = head;
  return true;
}

//3,链表显示
void D_Loop_List_Display(D_NODE *head)
{
  D_NODE *p = head->next;
  printf("链表数据:");
  while( p != head)
  {
    printf("%d ", p->data);
    p = p->next;
  }
  printf("\n");
}
//4,链表节点查找
bool D_Lool_List_Search(D_NODE *head, int data)
{
  int i = 1;
  D_NODE *p = head->next;
  while(p != head)
  {
    if (p->data == data)
    {
      printf("找到这个节点!,节点序号[%d]\n", i);
      return true;
    }
    p = p->next;
    i++;
  }
  printf("链表中没有这个节点!\n");
}

//5,链表节点删除
bool D_Loop_List_Remove(D_NODE *head, int data)
{
  int i = 1;
  D_NODE *p = head->next;
  while(p != head)
  {
    if (p->data == data)
    {
      printf("删除这个节点!,节点序号[%d]\n", i);
      p->prev->next = p->next;
      p->next->prev = p->prev;
      free(p);
      return true;
    }
    p = p->next;
    i++;
  }
  printf("链表中没有这个节点!\n"); 

}

//6,链表的销毁
void D_Lool_List_Destroy(D_NODE *head)
{
  int i = 0;
  D_NODE *p = head;
  while(p->next != head)
  {
    p = p->next;
    free(p->prev);
    i++;
  }
  free(p);
  printf("销毁链表成功,一共释放[%d]个节点!\n", i);
}

/*双向循环链表*/
int main(int argc, char const *argv[])
{
  int i, num;

  D_NODE *dl_list = D_Loop_List_Create();

  for(i=0; i<5; i++)
  {
    scanf("%d", &num);
    D_Loop_List_Insert_End(dl_list, num);
    D_Loop_List_Display(dl_list);
  }

  printf("请输入需要查找的数据:");
  scanf("%d", &num);
  D_Lool_List_Search(dl_list, num); 

  printf("请输入需要删除的数据:");
  scanf("%d", &num);
  D_Loop_List_Remove(dl_list, num);   

  D_Lool_List_Destroy(dl_list);

  return 0;
}




相关文章
|
3月前
|
存储 算法 Perl
数据结构实验之链表
本实验旨在掌握线性表中元素的前驱、后续概念及链表的建立、插入、删除等算法,并分析时间复杂度,理解链表特点。实验内容包括循环链表应用(约瑟夫回环问题)、删除单链表中重复节点及双向循环链表的设计与实现。通过编程实践,加深对链表数据结构的理解和应用能力。
75 4
|
1天前
|
存储 机器学习/深度学习 算法
C 408—《数据结构》算法题基础篇—链表(下)
408考研——《数据结构》算法题基础篇之链表(下)。
50 25
|
1天前
|
存储 算法 C语言
C 408—《数据结构》算法题基础篇—链表(上)
408考研——《数据结构》算法题基础篇之链表(上)。
33 16
|
26天前
|
机器学习/深度学习 存储 C++
【C++数据结构——线性表】单链表的基本运算(头歌实践教学平台习题)【合集】
本内容介绍了单链表的基本运算任务,涵盖线性表的基本概念、初始化、销毁、判定是否为空表、求长度、输出、求元素值、按元素值查找、插入和删除数据元素等操作。通过C++代码示例详细解释了顺序表和链表的实现方法,并提供了测试说明、通 - **任务描述**:实现单链表的基本运算。 - **相关知识**:包括线性表的概念、初始化、销毁、判断空表、求长度、输出、求元素值、查找、插入和删除等操作。 - **测试说明**:平台会对你编写的代码进行测试,提供测试输入和预期输出。 - **通关代码**:给出了完整的C++代码实现。 - **测试结果**:展示了测试通过后的预期输出结果。 开始你的任务吧,祝你成功!
35 5
|
2月前
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
|
3月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
92 5
|
3月前
|
算法
数据结构之购物车系统(链表和栈)
本文介绍了基于链表和栈的购物车系统的设计与实现。该系统通过命令行界面提供商品管理、购物车查看、结算等功能,支持用户便捷地管理购物清单。核心代码定义了商品、购物车商品节点和购物车的数据结构,并实现了添加、删除商品、查看购物车内容及结算等操作。算法分析显示,系统在处理小规模购物车时表现良好,但在大规模购物车操作下可能存在性能瓶颈。
64 0
|
8月前
|
存储 SQL 算法
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
|
8月前
|
存储 SQL 算法
LeetCode 题目 86:分隔链表
LeetCode 题目 86:分隔链表
|
8月前
|
存储 算法 Java
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
72 2

热门文章

最新文章