当前位置: 首页 > wzjs >正文

怎么找淘宝客网站城市建设投资公司网站

怎么找淘宝客网站,城市建设投资公司网站,从化网站建设服务,建设企业网站用动态还是静态欢迎拜访:雾里看山-CSDN博客 本篇主题:数据结构之带头双向循环链表 发布时间:2025.7.1 隶属专栏:数据结构 目录 概念与结构核心优势应用场景带头双向循环链表的实现创建结构体基本功能 接口实现初始化销毁创建节点打印链表长度 增…

欢迎拜访:雾里看山-CSDN博客
本篇主题:数据结构之带头双向循环链表
发布时间:2025.7.1
隶属专栏:数据结构

在这里插入图片描述

目录

  • 概念与结构
  • 核心优势
  • 应用场景
  • 带头双向循环链表的实现
    • 创建结构体
    • 基本功能 接口实现
      • 初始化
      • 销毁
      • 创建节点
      • 打印
      • 链表长度
    • 增删查改 接口实现
        • 头插
        • 尾插
        • 在pos位置插入
        • 头删
        • 尾删
        • 删除pos位置
    • 整体代码展示
  • 总结

概念与结构

带头双向循环链表(Doubly Circular Linked List with Head Node)是链表中最复杂但功能最完善的变体,它结合了四种特性:

  • 带头节点:包含一个不存储数据的哨兵节点(头节点)
  • 双向:每个节点同时包含前驱和后继指针
  • 循环:头尾节点相互连接形成环状结构
  • 链表:动态分配的非连续存储结构

核心优势

  • 统一操作逻辑:头节点消除边界条件处理
  • 高效双端操作:头插/头删/尾插/尾删均为O(1)
  • 任意位置操作:已知节点时插入/删除为O(1)
  • 完整遍历能力:从任意节点开始均可遍历整个链表
  • 内存利用率高:动态分配,无容量限制

应用场景

  1. 操作系统内核
    1. 进程调度队列
    2. 内存页管理
    3. 文件描述符表
  2. 数据库系统
    1. 事务日志管理
    2. 缓存淘汰算法实现(如LRU)
    3. 索引结构实现
  3. 图形用户界面
    1. 控件层级管理
    2. 撤销/重做历史记录
    3. 事件处理队列
  4. 游戏开发
    1. 游戏对象管理
    2. 动画序列控制
    3. 粒子系统管理
  5. 网络协议栈
    1. TCP连接管理
    2. 数据包重组队列
    3. 路由表实现

带头双向循环链表的实现

创建结构体

结构体需要包含两个指针和一个数据域。

typedef int LTDataType;   typedef struct ListNode
{struct ListNode* prev;// 指向前一个节点struct ListNode* next;// 指向后一个节点LTDataType value;     // 保存节点数据
}LTNode;

基本功能 接口实现

初始化

创建头结点,建立循环。

LTNode* LTInit()
{LTNode* phead = BuyLTNode(0);phead->next = phead;phead->prev = phead;return phead;
}

销毁

遍历数组,释放每一个节点的空间。

void LTDestory(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){LTNode* tmp = cur;cur = cur->next;free(tmp);}free(phead);	
}

创建节点

动态开辟一个节点,为其他接口提供一个已经开辟好空间的节点。

LTNode* BuyLTNode(LTDataType x)
{LTNode* node = (LTNode*)malloc(sizeof(LTNode));if (node == NULL){perror("malloc fail");exit(-1);}node->value = x;node->prev = NULL;node->next = NULL;return node;
}

打印

打印出链表中所有的节点,方便我们进行查看

void LTPrint(LTNode* phead)
{assert(phead);printf("phead<=>");LTNode* cur = phead->next;while (cur != phead){printf("%d<=>", cur->value);cur = cur->next;}printf("NULL\n");
}

链表长度

遍历链表一遍,计算出链表的长度

int LTSize(LTNode* phead)
{assert(phead);int size = 0;LTNode* cur = phead->next;while (cur != phead){size++;cur = cur->next;}return size;
}

增删查改 接口实现

头插

直接将节点插入到头结点后面即可

void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = BuyLTNode(x);LTNode* first = phead->next;newnode->prev = phead;phead->next = newnode;newnode->next = first;first->prev = newnode;
}
尾插

直接将节点插入到头结点之前即可

void LTPushBack(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = BuyLTNode(x);LTNode* tail = phead->prev;newnode->next = phead;phead->prev = newnode;newnode->prev = tail;tail->next = newnode;}
在pos位置插入
void LTInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* prev = pos->prev;LTNode* newnode = BuyLTNode(x);prev->next = newnode;newnode->prev = prev;pos->prev = newnode;newnode->next = pos;
}

头删

确保链表中有数据即可

void LTPopFront(LTNode* phead)
{assert(phead);assert(phead->next != phead);LTNode* first = phead->next;LTNode* second = first->next;free(first);phead->next = second;second->prev = phead;
}
尾删

同样需要判断链表中是否存有数据

void LTPopBack(LTNode* phead)
{assert(phead);assert(phead->next != phead);LTNode* tail = phead->prev;LTNode* tailprev = tail->prev;free(tail);tailprev->next = phead;phead->prev = tailprev;
}
删除pos位置

找到pos位置的前一个节点和后一个节点即可。

void LTErase(LTNode* pos)
{assert(pos);LTNode* posprev = pos->prev;LTNode* posnext = pos->next;free(pos);posprev->next = posnext;posnext->prev = posprev;}

遍历链表,找到正确的位置,返回其节点指针,如果数据不存在,则返回空指针。

LTNode* LTFind(LTNode* phead, LTDataType x)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){if (cur->value == x){return cur;}cur = cur->next;}return NULL;
}

并没有太多的技术含量,只是对节点内的数据修改一下。实现的目的是为了统一接口。

void LTModify(LTNode* pos, LTDataType x)
{assert(pos);pos->value = x;
}

整体代码展示

包含三个文件,分别是:List.hList.cmain.c
List.h:

#pragma once#include <stdio.h>
#include <assert.h>
#include <stdlib.h>typedef int LTDataType;typedef struct ListNode
{struct ListNode* prev;struct ListNode* next;LTDataType value;
}LTNode;LTNode* BuyLTNode(LTDataType x);
LTNode* LTInit();
void LTDestory(LTNode* phead);
void LTPrint(LTNode* phead);
void LTPushBack(LTNode* phead, LTDataType x);
void LTPopBack(LTNode* phead);void LTPushFront(LTNode* phead, LTDataType x);
void LTPopFront(LTNode* phead);int LTSize(LTNode* phead);LTNode* LTFind(LTNode* phead, LTDataType x);void LTInsert(LTNode* pos, LTDataType x);
void LTErase(LTNode* pos);void LTModify(LTNode* pos, LTDataType x);

List.c:

#include "List.h"LTNode* BuyLTNode(LTDataType x)
{LTNode* node = (LTNode*)malloc(sizeof(LTNode));if (node == NULL){perror("malloc fail");exit(-1);}node->value = x;node->prev = NULL;node->next = NULL;return node;
}
LTNode* LTInit()
{LTNode* phead = BuyLTNode(0);phead->next = phead;phead->prev = phead;return phead;
}
void LTDestory(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){LTNode* tmp = cur;cur = cur->next;free(tmp);}free(phead);	
}
void LTPrint(LTNode* phead)
{assert(phead);printf("phead<=>");LTNode* cur = phead->next;while (cur != phead){printf("%d<=>", cur->value);cur = cur->next;}printf("NULL\n");
}
void LTPushBack(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = BuyLTNode(x);LTNode* tail = phead->prev;newnode->next = phead;phead->prev = newnode;newnode->prev = tail;tail->next = newnode;}
void LTPopBack(LTNode* phead)
{assert(phead);assert(phead->next != phead);LTNode* tail = phead->prev;LTNode* tailprev = tail->prev;free(tail);tailprev->next = phead;phead->prev = tailprev;}void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = BuyLTNode(x);LTNode* first = phead->next;newnode->prev = phead;phead->next = newnode;newnode->next = first;first->prev = newnode;}
void LTPopFront(LTNode* phead)
{assert(phead);assert(phead->next != phead);LTNode* first = phead->next;LTNode* second = first->next;free(first);phead->next = second;second->prev = phead;}int LTSize(LTNode* phead)
{assert(phead);int size = 0;LTNode* cur = phead->next;while (cur != phead){size++;cur = cur->next;}return size;
}LTNode* LTFind(LTNode* phead, LTDataType x)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){if (cur->value == x){return cur;}cur = cur->next;}return NULL;
}void LTInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* prev = pos->prev;LTNode* newnode = BuyLTNode(x);prev->next = newnode;newnode->prev = prev;pos->prev = newnode;newnode->next = pos;
}
void LTErase(LTNode* pos)
{assert(pos);LTNode* posprev = pos->prev;LTNode* posnext = pos->next;free(pos);posprev->next = posnext;posnext->prev = posprev;}
void LTModify(LTNode* pos, LTDataType x)
{assert(pos);pos->value = x;
}

main.c:

#include"List.h"void TestList1()
{LTNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPushBack(plist, 5);LTPrint(plist);LTPushFront(plist, 10);LTPushBack(plist, 10);LTPrint(plist);
}void TestList2()
{LTNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPushBack(plist, 5);LTPrint(plist);LTPopBack(plist);LTPopFront(plist);LTPrint(plist);LTPopFront(plist);LTPopFront(plist);LTPopFront(plist);//LTPopFront(plist);LTPrint(plist);
}void TestList3()
{LTNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPushBack(plist, 5);LTPrint(plist);LTPushFront(plist, 10);LTPushFront(plist, 20);LTPushFront(plist, 30);LTPushFront(plist, 40);LTPrint(plist);
}void TestList4()
{LTNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPushBack(plist, 5);LTPrint(plist);LTPopFront(plist);LTPrint(plist);LTPopBack(plist);LTPrint(plist);
}int main()
{TestList4();return 0;
}

总结

带头双向循环链表作为链表结构的终极形态,具有以下核心价值:

  1. 操作统一性:头节点消除了所有边界条件
  2. 极致效率:所有位置插入删除均为O(1)操作
  3. 遍历灵活性:支持双向遍历和循环访问
  4. 内存安全性:明确的内存管理边界

尽管实现相对复杂,但在需要高性能和灵活性的系统级开发中(如操作系统内核、数据库引擎),带头双向循环链表是不可替代的基础数据结构。Linux内核中的list_head结构就是其典型应用,证明了这种数据结构在工业级系统中的重要价值。

⚠️ 写在最后:以上内容是我在学习以后得一些总结和概括,如有错误或者需要补充的地方欢迎各位大佬评论或者私信我交流!!!


文章转载自:

http://6t9VFyuT.csjps.cn
http://ppubQOLx.csjps.cn
http://WsPD4eck.csjps.cn
http://c2iHchUr.csjps.cn
http://2FSF865K.csjps.cn
http://ThPf7MBy.csjps.cn
http://ArFb95Hf.csjps.cn
http://5vZnxZaq.csjps.cn
http://upUbHypX.csjps.cn
http://ALwUTwik.csjps.cn
http://SahzqGMH.csjps.cn
http://KUaOavK8.csjps.cn
http://o0R0Ldr4.csjps.cn
http://AEU3Q0Sg.csjps.cn
http://1dZ9kiIq.csjps.cn
http://9vrVyQdy.csjps.cn
http://8RZFFvyc.csjps.cn
http://LH7JxWHl.csjps.cn
http://hvwQeSfO.csjps.cn
http://uOanxzql.csjps.cn
http://sXMzut22.csjps.cn
http://WaFsFREr.csjps.cn
http://t7cnhZQB.csjps.cn
http://NxJ33wVa.csjps.cn
http://yNzAe7t6.csjps.cn
http://h2ca1BF6.csjps.cn
http://4cQZSnsP.csjps.cn
http://ZwCutNtx.csjps.cn
http://pKmwtop3.csjps.cn
http://zCn2onbq.csjps.cn
http://www.dtcms.com/wzjs/704436.html

相关文章:

  • 北京app建设 网站开发公司做暧昧免费视频大全网站
  • 网站直接跳转前端机构培训
  • 杭州哪家做网站展示型网站建设的标准
  • 上海 网站建设官网mini1cn下载迷你世界登录
  • 2023免费推广网站seo网站文章编辑软件
  • 一个页面的网站wordpress 插件交互
  • 门户网网站建设功能需求表网站开发公司徐州
  • 随县网站建设网络营销外包推广效果
  • 网站开发的最初阶段包括合肥网站建设代理商
  • 男女直接做那个视频网站网络营销工具有哪些?
  • 个人房源网谷歌外贸网站seo怎么做
  • 产品展示类网站源码品牌网站建站公司
  • 装修网名搜狗seo软件
  • 珠海新盈科技 网站建设做网站怎样建立服务器
  • 德州建网站宜昌怎样优化网站建设
  • 杭州模板做网站用asp做的大型网站
  • 手机网站的好外太原网站优化常识
  • 长沙企业网站优化wordpress 使用两个主题
  • 成都网站建设学习oa系统入口
  • 学做网站 书页面设计要怎么做
  • 福州 网站建设搜索引擎下载安装
  • 狠狠做网站改成什么了福州营销型网站建设公司
  • 网站推广公司成功的经典案例做网站最大的公司
  • wordpress主题网站模板wordpress主题的使用
  • 凡科建站下载wordpress 文章转繁体
  • 二类电商用网站怎么做H5页面个人微网站怎么做
  • 网站建设项目经验泊头网站建设公司
  • 期末成绩怎么做网站cc wordpress
  • 工装公司十大排名网站优化推广方法
  • 深圳市建设管理中心网站潍坊可以做网站的公司