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

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

一、单向循环链表

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

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;
}




目录
打赏
0
0
0
0
26
分享
相关文章
Python 实现单向链表,和单向链表的反转
链表是一种数据结构,每个节点存储相邻节点的位置信息。单链表中的节点仅存储下一节点的位置。通过Python实现单链表,定义`ListNode`类并关联节点可创建链表。例如,创建A-&gt;B-&gt;C的链表后,可通过反转函数`reverse`将链表反转为CBA。代码展示了如何实现和操作单链表。
Python 实现单向链表,和单向链表的反转
|
4月前
|
【数据结构】双向带头循环链表(c语言)(附源码)
本文介绍了双向带头循环链表的概念和实现。双向带头循环链表具有三个关键点:双向、带头和循环。与单链表相比,它的头插、尾插、头删、尾删等操作的时间复杂度均为O(1),提高了运行效率。文章详细讲解了链表的结构定义、方法声明和实现,包括创建新节点、初始化、打印、判断是否为空、插入和删除节点等操作。最后提供了完整的代码示例。
140 0
|
5月前
|
[数据结构] -- 双向循环链表
[数据结构] -- 双向循环链表
39 0
|
5月前
|
数据结构与算法学习六:单向环形链表应用实例的约瑟夫环问题
这篇文章通过单向环形链表的应用实例,详细讲解了约瑟夫环问题的解决方案,并提供了Java代码实现。
47 0
|
5月前
数据结构的带头,双向,循环链表来咯
数据结构的带头,双向,循环链表来咯
36 0
|
5月前
|
【初阶数据结构】深入解析带头双向循环链表:探索底层逻辑
【初阶数据结构】深入解析带头双向循环链表:探索底层逻辑
【初阶数据结构】深入解析单链表:探索底层逻辑(无头单向非循环链表)(二)
【初阶数据结构】深入解析单链表:探索底层逻辑(无头单向非循环链表)
|
6天前
|
STL——栈和队列和优先队列
通过以上对栈、队列和优先队列的详细解释和示例,希望能帮助读者更好地理解和应用这些重要的数据结构。
17 4
☀☀☀☀☀☀☀有关栈和队列应用的oj题讲解☼☼☼☼☼☼☼
### 简介 本文介绍了三种数据结构的实现方法:用两个队列实现栈、用两个栈实现队列以及设计循环队列。具体思路如下: 1. **用两个队列实现栈**: - 插入元素时,选择非空队列进行插入。 - 移除栈顶元素时,将非空队列中的元素依次转移到另一个队列,直到只剩下一个元素,然后弹出该元素。 - 判空条件为两个队列均为空。 2. **用两个栈实现队列**: - 插入元素时,选择非空栈进行插入。 - 移除队首元素时,将非空栈中的元素依次转移到另一个栈,再将这些元素重新放回原栈以保持顺序。 - 判空条件为两个栈均为空。
|
2月前
|
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
158 77