数据结构之带头结点的双向循环链表(含全部代码)

简介: 数据结构之带头结点的双向循环链表(含全部代码)

带头结点的双向循环链表的实现

带头结点的双向循环链表和单链表相比具有许多的优点,增删查改更加的便捷,时间复杂度均为O(1)

头文件创建

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>

定义数据类型以及创建链表结点

typedef int DataType;
typedef struct ListNode
{
  struct ListNode* prev;
  struct ListNode* next;
  DataType data;
}LN;

所需要实现的函数

//初始化
LN* ListInit();
//创建结点
LN* BuyListNode(DataType x);
//销毁链表
void ListDestory(LN* phead);
//打印链表
void ListPrint(LN* phead);
//头插
void ListPushFront(LN* phead, DataType x);
//尾插
void ListPushBack(LN* phead, DataType x);
//头删
void ListPopFront(LN* phead);
//尾删
void ListPopBack(LN* phead);
//查找x并返回x结点位置
LN* ListFind(LN* phead, DataType x);
//在pos前插入x
void ListInsert(LN* pos, DataType x);
//删除pos处的元素
void ListErase(LN* pos);
//判断链表是否为空
bool ListEmpty(LN* phead);
//计算元素个数
int ListSize(LN* phead);

函数的实现

#include"DList.h"
//初始化
LN* ListInit()
{
  LN* phead = BuyListNode(0);
  phead->next = phead;
  phead->prev = phead;
  return phead;
}
//创建结点
LN* BuyListNode(DataType x)
{
  LN* newnode = (LN*)malloc(sizeof(LN));
  if (newnode == NULL)
  {
    printf("malloc fail");
    exit(-1);
  }
  else
  {
    newnode->data = x;
    newnode->prev = NULL;
    newnode->next = NULL;
    return newnode;
  }
}
//销毁链表
void ListDestory(LN* phead)
{
  assert(phead);
  LN* cur = phead->next;
  while (cur != phead)
  {
    LN* next = cur->next;
    free(cur);
    cur = next;
  }
  free(phead);
  phead = NULL;
}
//打印链表
void ListPrint(LN* phead)
{
  assert(phead);
  LN* cur = phead->next;
  while (cur != phead)
  {
    printf("%d ", cur->data);
    cur = cur->next;
  }
  printf("\n");
}
//头插
void ListPushFront(LN* phead, DataType x)
{
  assert(phead);
  LN* newnode = BuyListNode(x);
  LN* first = phead->next;
  phead->next = newnode;
  newnode->prev = phead;
  newnode->next = first;
  first->prev = newnode;
}
//尾插
void ListPushBack(LN* phead, DataType x)
{
  assert(phead);
  LN* tail = phead->prev;
  LN* newnode = BuyListNode(x);
  tail->next = newnode;
  newnode->prev = tail;
  phead->prev = newnode;
  newnode->next = phead;
}
//头删
void ListPopFront(LN* phead)
{
  assert(phead);
  assert(phead->next != phead);
  LN* first = phead->next;
  phead->next = first->next;
  first->next->prev = phead;
  free(first);
  first = NULL;
}
//尾删
void ListPopBack(LN* phead)
{
  assert(phead);
  assert(phead->next != phead);
  LN* tail = phead->prev;
  //phead->prev = tail->prev;
  tail->prev->next = phead;
  phead->prev = tail->prev;
  free(tail);
  tail = NULL;
}
//查找x并返回x结点位置
LN* ListFind(LN* phead, DataType x)
{
  assert(phead);
  LN* cur = phead->next;
  while (cur != phead)
  {
    if (cur->data == x)
    {
      return cur;
    }
    cur = cur->next;
  }
  return NULL;
}
//在pos前插入x
void ListInsert(LN* pos, DataType x)
{
  assert(pos);
  LN* newnode = BuyListNode(x);
  LN* prev = pos->prev;
  prev->next = newnode;
  newnode->prev = prev;
  newnode->next = pos;
  pos->prev = newnode;
}
//删除pos处的元素
void ListErase(LN* pos)
{
  assert(pos);
  LN* prev = pos->prev;
  LN* next = pos->next;
  prev->next = next;
  next->prev = prev;
  free(pos);
  pos = NULL;
}
//判断链表是否为空
bool ListEmpty(LN* phead)
{
  if (phead == NULL)
  {
    return true;
  }
  else
  {
    return false;
  }
}
//计算元素个数
int ListSize(LN* phead)
{
  int size = 0;
  assert(phead);
  LN* cur = phead->next;
  while (cur != phead)
  {
    size++;
    cur = cur->next;
  }
  return size;
}
目录
相关文章
|
2月前
|
存储 算法 Perl
数据结构实验之链表
本实验旨在掌握线性表中元素的前驱、后续概念及链表的建立、插入、删除等算法,并分析时间复杂度,理解链表特点。实验内容包括循环链表应用(约瑟夫回环问题)、删除单链表中重复节点及双向循环链表的设计与实现。通过编程实践,加深对链表数据结构的理解和应用能力。
73 4
|
12天前
|
机器学习/深度学习 存储 C++
【C++数据结构——线性表】单链表的基本运算(头歌实践教学平台习题)【合集】
本内容介绍了单链表的基本运算任务,涵盖线性表的基本概念、初始化、销毁、判定是否为空表、求长度、输出、求元素值、按元素值查找、插入和删除数据元素等操作。通过C++代码示例详细解释了顺序表和链表的实现方法,并提供了测试说明、通 - **任务描述**:实现单链表的基本运算。 - **相关知识**:包括线性表的概念、初始化、销毁、判断空表、求长度、输出、求元素值、查找、插入和删除等操作。 - **测试说明**:平台会对你编写的代码进行测试,提供测试输入和预期输出。 - **通关代码**:给出了完整的C++代码实现。 - **测试结果**:展示了测试通过后的预期输出结果。 开始你的任务吧,祝你成功!
30 5
|
26天前
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
88 5
|
2月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
82 1
|
2月前
|
算法
数据结构之购物车系统(链表和栈)
本文介绍了基于链表和栈的购物车系统的设计与实现。该系统通过命令行界面提供商品管理、购物车查看、结算等功能,支持用户便捷地管理购物清单。核心代码定义了商品、购物车商品节点和购物车的数据结构,并实现了添加、删除商品、查看购物车内容及结算等操作。算法分析显示,系统在处理小规模购物车时表现良好,但在大规模购物车操作下可能存在性能瓶颈。
61 0
|
2月前
|
C语言
【数据结构】双向带头循环链表(c语言)(附源码)
本文介绍了双向带头循环链表的概念和实现。双向带头循环链表具有三个关键点:双向、带头和循环。与单链表相比,它的头插、尾插、头删、尾删等操作的时间复杂度均为O(1),提高了运行效率。文章详细讲解了链表的结构定义、方法声明和实现,包括创建新节点、初始化、打印、判断是否为空、插入和删除节点等操作。最后提供了完整的代码示例。
96 0
|
2月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
286 9
|
2月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
44 1
|
12天前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
128 75

热门文章

最新文章