【数据结构初阶】双向带头循环链表原来是纸老虎,结构复杂,操作简单

简介: 【数据结构初阶】双向带头循环链表原来是纸老虎,结构复杂,操作简单

6ec171f1317b488ca896a71ae27c57f6.png

双向带头循环链表:结构复杂,操作简单

0.结构体定义

这里方便浏览,特地没有将int类型重命名为TLDateType

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
struct ListNode
{
  int val;
  struct ListNode* prev;
  struct ListNode* next;
};

1.初始化

  1. 带头需要初始化一个哨兵位头结点
  2. 传二级指针
  3. 初始化自己的prev和next都指向自己
void ListInit(struct ListNode** pphead)
{
  struct ListNode* Guard = (struct ListNode*)malloc(sizeof(struct ListNode));
  if (Guard == NULL)
  {
    perror("ListInit");
    return;
  }
  *pphead = Guard;
  Guard->next = Guard;
  Guard->prev = Guard;
}

2.尾插

  1. 一级指针
  2. 直接prev找尾
  3. 即是无首元结点,也可(头结点自环)
struct ListNode* BuyListNode(int x)
{
  struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
  if (newnode == NULL)
  {
    perror("BuySListNode");
    return NULL;
  }
  newnode->val = x;
  newnode->prev = NULL;
  newnode->next = NULL;
  return newnode;
}
void ListPushBack(struct ListNode* phead,int x)
{
  assert(phead);
  struct ListNode* newnode = BuyListNode(x);
  struct ListNode* tail = phead->prev;
  newnode->next = phead;
  phead->prev = newnode;
  tail->next = newnode;
  newnode->prev = tail;
}

3.打印

  1. 可assert断言(建议单链表不用断言)---头结点
  2. 起始条件cur=phead->next;
  3. 循环终止条件cur==phead
void ListPrint(struct ListNode* phead)
{
  assert(phead);
  struct ListNode* cur = phead->next;
  while (cur != phead)
  {
    printf("%d->", cur->val);
    cur = cur->next;
  }
  printf("NULL\n");
}

4.头插

  1. 一级指针
  2. 即是无首元结点,也可(头结点自环)
void ListPushFront(struct ListNode* phead,int x)
{
  assert(phead);
  struct ListNode* newnode = BuyListNode(x);
  struct ListNode* next = phead->next;
  newnode->next = next;
  next->prev = newnode;
  phead->next = newnode;
  newnode->prev = phead;
}

5.任意位置插入前面位置

  1. 因为有prev,前插不同phead
  2. 尾插,头插就用ListInsert传不同pos参数
  3. 如果pos传phead,就相当于于是尾插
  4. 如果pos传phead->next,就相当于于是头插
void ListInsert(struct ListNode* pos, int x)
{
  assert(pos);
  struct ListNode* newnode = BuyListNode(x);
  struct ListNode* prev = pos->prev;
  prev->next = newnode;
  newnode->prev = prev;
  newnode->next = pos;
  pos->prev = newnode;
}
头插:ListNode(phead->next,x);
尾插:ListNode(phead,x);

6.尾删

  1. 不为空,!ListEmpty(plhead)
  2. prev,tail,phead
bool ListEmpty(struct ListNode* phead)
{
  return phead->next == phead;
}
void ListPopBack(struct ListNode* phead)
{
  assert(phead);
  assert(!ListEmpty(phead));
  struct ListNode* tail = phead->prev;
  struct ListNode* prev = tail->prev;
  prev->next = phead;
  phead->prev = prev;
  free(tail);
  tail = NULL;
}

7.头删

  1. 不为空,!ListEmpty(plhead)
  2. phead,first,second
void ListPopFront(struct ListNode* phead)
{
  assert(phead);
  assert(!ListEmpty(phead));
  struct ListNode* first = phead->next;
  struct ListNode* second = first->next;
  phead->next = second;
  second->prev = phead;
  free(first);
  first = NULL;
}

8.链表长度

  1. 起始条件:cur=phead->next
  2. 终止条件:cur!=phead;
size_t ListSize(struct ListNode* phead)
{
  size_t size = 0;
  struct ListNode* cur = phead->next;
  while (cur != phead)
  {
    ++size;
    cur = cur->next;
  }
  return size;
}

9.任意位置删除当前位置

  1. 不为空,!ListEmpty(plhead)
  2. 尾删,头删就用ListErase传不同pos参数
  3. 如果pos传phead->prev,就是尾删
  4. 如果pos传phead->next,就是头删
void ListErase(struct ListNode* pos)
{
  assert(pos);
  struct ListNode* prev = pos->prev;
  struct ListNode* next = pos->next;
  prev->next = next;
  next->prev = prev;
  free(pos);
  pos = NULL;
}

10. 销毁

  1. 看是否保留哨兵头,来传一级或二级指针
  2. 先保留哨兵头作为判断循环条件,最后决定是否释放哨兵头
void ListDestory(struct ListNode** pphead)
{
  assert(pphead);
  struct ListNode* cur = (*pphead)->next;
  while (cur != *pphead)
  {
    struct ListNode* next = cur->next;
    free(cur);
    cur = next;
  }
  free(*pphead);
  *pphead = NULL;
}
目录
相关文章
|
5小时前
|
存储
数据结构第二课 -----线性表之单向链表
数据结构第二课 -----线性表之单向链表
|
5小时前
|
存储 算法 Java
数据结构与算法 数组和链表
数据结构与算法 数组和链表
11 0
|
5小时前
|
存储 Java
深入浅出数据结构之链表
深入浅出数据结构之链表
|
5小时前
|
C++
数据结构(双链表
数据结构(双链表
8 1
|
5小时前
|
存储 缓存
[数据结构]~双向+循环链表从(0~1)
[数据结构]~双向+循环链表从(0~1)
|
5小时前
|
存储
数据结构第三课 -----线性表之双向链表
数据结构第三课 -----线性表之双向链表
|
5小时前
|
存储 Java
数据结构奇妙旅程之顺序表和链表
数据结构奇妙旅程之顺序表和链表
|
5小时前
|
存储 C语言
数据结构基础:双链表结构、实现
数据结构基础:双链表结构、实现
|
5小时前
|
存储
数据结构基础:一篇文章教你单链表(头插,尾插,查找,头删等的解析和代码)
数据结构基础:一篇文章教你单链表(头插,尾插,查找,头删等的解析和代码)
|
5小时前
|
C语言
数据结构:5、链表之双向链表
数据结构:5、链表之双向链表
25 0