算法导论之九链表

算法导论 XOR双向循环链表——内存高效链表 XOR双向循环链表——内存高效双向链表1. 算法导论原题 10.2-8 ? Explain how to implement doubly linked lists using only one pointer value x.np per item instead of the usual two(next and pre). Assume that all pointer values 阅读详情

1.     与数组不同,链表的顺序是由各个对象里的指针决定的。双向链表L的每一个元素都是一个对象,每个对象有一个关键字key和两个指针next和prev。设x为链表的一个元素,x.next指向的它在链表中的后继元素,x.prev指向它的前驱元素。如果x.prev=NIL,

则元素x是链表的头,若x.next=NIL,则x是链表的尾。若L.head=NIL,则链表为空。

2.     循环链表中,表头元素的prev指针指向表尾元素,而表尾元素的next指针则指向表头元素。

3.     链表的搜索,过程LIST-SEARCH(L,k)采用简单的线性搜索方法,用于查找链表L中的第一个关键字为k的元素,并返回指向该元素的指针。

LIST-SERACH(L,k)

       x = L.head

       while x != NIL and x.key != k

              x = x.next

       return x

4.     链表的插入,过程LIST-INSERT(L,x)将x“连接入”到链表的前端

LIST-INSERT(L,x)

       x.next = L.head

       if L.head !=NIL

              L.head.prev = x

       L.head = x

       x.prev = NIL

5.     链表的删除,过程LIST-DELETE(L,x)将一个元素x从链表L中移除。

LIST-DELETE(L,x)

       if x.prev != NIL

              x.prev.next = x.next

       else L.head = x.next

       if x.next != NIL

              x.next.prev = x.prev

6.     单链表的程序代码如下:

#include <STDIO.H>

#include <STDLIB.H>

#include <STRING.H>

 

typedef int elemType;

 

//定义单链表的结点类型

typedef struct Node

{

       elemTypeelement;

       Node*next;

}Node;

 

 

//初始化线性表

void initList(Node **pNode)

{

       *pNode= NULL;

       printf("initList函数执行,初始化成功\n");

}

 

//创建线性表,此函数输入负数终止读取数据

Node *createList(Node *pHead)

{

       Node*p1,*p2;

       p1= p2 = (Node*)malloc(sizeof(Node));

 

       if(p1 == NULL || p2 == NULL)

       {

              printf("内存分配失败\n");

              exit(0);

       }

 

       memset(p1,0,sizeof(Node));

 

       scanf("%d",&p1->element);  //输入新结点

       p1->next= NULL;        //新结点的指针置空

 

       while(p1->element > 0)

       {

              if(pHead == NULL)

              {

                     pHead= p1;    //空表,接入表头

              }

              else

              {

                     p2->next= p1; //非空表,接入表尾

              }

 

              p2= p1;

 

              p1= (Node*)malloc(sizeof(Node));      //重新申请一个结点

              if(p1 == NULL || p2 == NULL)

              {

                     printf("内存分配失败\n");

                     exit(0);

              }

 

              memset(p1,0,sizeof(Node));

             

              scanf("%d",&p1->element);  //输入新结点

              p1->next= NULL;

       }

 

       printf("createList函数执行,链表创建成功\n");

       returnpHead;  //返回链表的头指针

}

 

//打印链表,链表的遍历

void printList(Node *pHead)

{

       if(pHead == NULL)

       {

              printf("printList函数执行,链表为空\n");

              return;

       }

       else

       {

              while(pHead != NULL)

              {

                     printf("%d",pHead->element);

                     pHead= pHead->next;

              }

              printf("\n");

       }

}

 

//清除链表中的所有元素,释放单链表L中所有的结点,使之成为一个空表

void clearList(Node *pHead)

{

       Node*pNext; //定义一个与pHead相邻节点

 

       if(pHead == NULL)

       {

              printf("printList函数执行,链表为空\n");

              return;

       }

       while(pHead->next!= NULL)

       {

              pNext= pHead->next;   //保存下一个结点的指针

              free(pHead);

              pHead= pNext;      //表头下移

       }

       printf("clearList函数执行,链表已清除\n");

}

 

//返回单链表的长度

int sizeList(Node *pHead)

{

       intsize = 0;

       while(pHead != NULL)

       {

              size++;    //遍历链表的size比链表的实际长度小1

              pHead= pHead->next;

       }

       printf("sizeList函数执行,链表长度%d \n",size);

       returnsize;

}

 

//检查单链表是否为空

int isEmptyList(Node *pHead)

{

       if(pHead == NULL)

       {

              printf("isEmptyList函数执行,链表为空\n");

              return1;

       }

       else

              printf("isEmptyList函数执行,链表非空\n");

       return0;

}

 

//返回单链表中的第pos个节点中的元素

elemType getElement(Node *pHead,int pos)

{

       inti = 0;

 

       if(pos < 1)

       {

              printf("getElement函数执行,pos值非法\n");

              return0;

       }

 

       if(pHead == NULL)

       {

              printf("getElement函数执行,链表为空");

              return0;

       }

 

       while(pHead != NULL)

       {

              ++i;

              if(i == pos)

              {

                     break;

              }

              pHead= pHead->next;   //移到下一节点

       }

 

       if(i < pos)

       {

              printf("getElement函数执行,pos值超出链表长度\n");

              return0;

       }

 

       returnpHead->element;

}

 

//从单链表中查找具有给定值x的第一个元素,成功则返回该结点data的存储地址,否则返回NULL

elemType *getElemAddr(Node*pHead, elemType x)

{

       if(pHead == NULL)

       {

              printf("getElemAddr函数执行,链表为空");

              return0;

       }

 

       if(x < 0)

       {

              printf("getElemAddr函数执行,给定x值非法\n");

              return0;

       }

 

       //判断是否到链表末尾,以及是否存在所要找的元素

       while((pHead->element != x) && (NULL != pHead->next))

       {

              pHead= pHead->next;

       }

 

       if((pHead->element != x) && pHead != NULL)

       {

              printf("getElemAddr函数执行,在链表中未找到x值\n");

              return0;

       }

 

       if(pHead->element == x)

       {

              printf("getElemAddr函数执行,元素%d 的地址为0x%x\n",x,&(pHead->element));

       }

 

       return&(pHead->element);

}

 

//把单链表中的第pos个节点的值修改为x的值

int modifyElem(Node *pNode, intpos, elemType x)

{

       Node*pHead;

       pHead= pNode;

       inti = 0;

 

       if(pHead == NULL)

       {

              printf("modifyElem函数执行,链表为空\n");

              return0;

       }

 

       if(pos < 1)

       {

              printf("modifyElem函数执行,pos值非法\n");

              return0;

       }

 

       while(pHead != NULL)

       {

              ++i;

              if(i == pos)

              {

                     break;

              }

              pHead= pHead->next;

       }

 

       if(i < pos)

       {

              printf("modifyElem函数执行,pos值超出链表长度\n");

              return0;

       }

 

       pNode= pHead;

       pNode->element= x;

       printf("modifyElem函数执行\n");

       return1;

}

 

//向单链表的表头插入一个元素

int insertHeadList(Node **pNode,elemType insertElem)

{

       Node*pInsert;

       pInsert= (Node*)malloc(sizeof(Node));

       memset(pInsert,0,sizeof(Node));

 

       pInsert->element= insertElem;

       pInsert->next= *pNode;

       *pNode= pInsert;

 

       printf("insertHeadList函数执行,向表头插入元素成功\n");

 

       return1;

}

 

//向单链表的末尾添加一个元素

int insertLastList(Node**pNode,elemType insertElem)

{

       Node*pInsert,*pHead,*pTemp;

 

       pHead= *pNode;

       pTemp= pHead;

       pInsert= (Node*)malloc(sizeof(Node));

       memset(pInsert,0,sizeof(Node));

 

       pInsert->element= insertElem;

 

       while(pHead->next != NULL)

       {

              pHead= pHead->next;

       }

 

       pHead->next= pInsert;

       *pNode= pTemp;

 

       printf("insertLastList函数执行,向表尾插入元素成功\n");

 

       return1;

}

 

//////////////////////////////////////////////////////////////////////////

int main()

{

       Node*pList = NULL;

       intlength = 0;

 

       elemTypeposElem;

 

       initList(&pList);

       printList(pList);

 

       pList= createList(pList);

       printList(pList);

 

       sizeList(pList);

 

       isEmptyList(pList);

 

       posElem= getElement(pList,3);

       printf("getElement函数执行,位置3 中的元素为 %d\n",posElem);

       printList(pList);

 

       getElemAddr(pList,5);

 

       modifyElem(pList,4,1);

       printList(pList);

 

       insertHeadList(&pList,12);

       printList(pList);

 

       insertLastList(&pList,10);

       printList(pList);

 

       clearList(pList);

       system("pause");

 

       return0;

}

算法导论 - 基于 C# 的链表实现 链表是一种灵活且高效的基础数据结构,适用于需要频繁插入和删除操作的场景。通过本文档,您应能够理解单向链表的基本原理及其在 C# 中的实现,并能够在合适的场景中应用这一数据结构。 阅读详情

相关推荐

算法导论 习题 10.2

10.2-1: INSERT可以,DELETE不可以 10.2-2,10.2-3: 写代码(略) 10.2-4:在LIST-SEARCH过程中,如何在每次迭代中省去对x!=nil[L]的检查? 把你要查找的值,存放在哨兵里头,这样当循环往下走的时候,匹配到了找到的值就不会再往下走了。这个时候判断x的位置是否在哨兵,不是返回下标,是的话,返回NULL。

到处是小雪的白色世界 724

C语言单链表实现19个功能完全详解

最近在复习数据结构,想把数据结构里面涉及的都自己实现一下,完全是用C语言实现的。   自己编写的不是很好,大家可以参考,有错误希望帮忙指正,现在正处于编写阶段,一共将要实现19个功能。到目前我只写了一半,先传上来,大家有兴趣可以帮忙指正,谢谢。   在vs2010上面编译运行无错误。   每天都会把我写的新代码添加到这个里面。直到此链表完成。 以下是关于线性表链接存储单链表操作的1

Sergi0的博客 824

算法导论核心代码精粹

本文摘要整理了《算法导论》中的核心算法C++实现,涵盖分治、动态规划、图算法等内容。主要内容包括: 基础算法实现 分治算法:归并排序、快速排序、最大子数组问题 动态规划:钢条切割、矩阵链乘法、最长公共子序列 贪心算法:活动选择、霍夫曼编码 图算法 BFS/DFS遍历 Dijkstra最短路径 拓扑排序 多源最短路径(Floyd-Warshall) 典型应用场景 社交网络好友推荐 公交/地铁路径规划 无人机巡检路径 电动汽车充电导航 迷宫游戏求解 优化技术 并行计算(OpenMP) 遗传算法优化 双向BFS搜

keny-大成的博客 1114

RT-Thread内核中链表介绍

不管是学习分析FreeRTOS内核,还是学习分析RT-Thread内核源码;对内核中链表的相关定义的熟悉,以及API的使用是必不可少的。因为,在内核中很多其它组件的相关API函数,都要用到进行对象的管理。本文简要介绍RT-Thread Nano内核中双向循环链表和单向链表的定义,以及API相关源码分析。 1.双向循环链表介绍 双向循环链表结构体定义: /** * Double List structure * 双向循环链表结构体定义 */ struct rt_list_node { s

caihaitao2000的博客 1049

算法导论系列入门书籍算法导论

作者:禅与计算机程序设计艺术 1.简介 一、课程简介 《算法导论》是一本由布莱恩·克尼根()、艾伦·麦克法兰()、马修·卡尔曼()、约翰·霍尔巴赫()等著,英文版由J.K. Tarjan译成中文的经典计算机科学教材

AI天才研究院 2259

《算法导论》C++代码实现:深入算法世界

在计算机科学中,算法是一系列定义明确的操作步骤,用于解决特定问题或执行特定的任务。掌握算法的基本原理,对于IT行业的从业者而言,不仅能够提高编程效率,还可以优化程序性能,为解决复杂问题打下坚实基础。public:// 数据成员,表示点的坐标// 构造函数// 成员函数,计算两点间的距离这个简单的类Point拥有两个公共数据成员x和y,代表二维空间中的一个点。成员函数distanceTo用来计算当前点与另一个点之间的距离。C++中的类是一种复合数据类型,能够封装数据及其操作。

weixin_32999557的博客 1063

RT-Thread 隐藏的宝藏之双链表

1. 单链表与双链表 单链表: 由一个个节点(node)组成,每个节点都有指向下一个节点的指针。节点的连接方向是单向的,节点之间用指针连起来,所有结构体类型可以不一样,链表的大小也可以动态变化。但是不能随机访问数据,只能遍历。 双链表:由一个个节点(node)组成,每个节点都有指向下一个节点的指针,每个节点都有一个指向上一个节点的指针。所以节点的连接方向是双向的,节点之间用指针连起来,所有结构体类型可以不一样,链表的大小也可以动态变化。但是不能随机访问数据,只能遍历。 可以得出结论:单链表和双链表主要的区别

whj123999的博客 889

SNN目标识别MNIST

总体来说这篇论文提出的方法用了多种更精密的细节,如LIF膜电位公式,三种STDP方法,但我觉得还可以有很大的改进,比如输入层全连接到兴奋层,兴奋层通过抑制层实现的侧向抑制,抑制层不参与学习等等。尤其是兴奋层通过抑制层实现侧向抑制这里,当神经元兴奋时,通过抑制层再倒回兴奋层,所抑制的已经经过一了一段时间的延迟。如有错误,请不吝赐教。

m0_74982304的博客 1262

RT-Thread源码-核心数据结构rt_list及rt_slist

在RT-Thread中,基本上所有内核对象的实现都离不开,rt_list及rt_slist,这两个数据结构实际上就是普通的链表数据结构。 rt_list表示的是双向链表结构,而rt_slist表示的是单向链表结构,以下为这两个数据结构的实现: struct rt_list_node { struct rt_list_node *next; /**< point to next node. */ struct rt_list_node.

qq_36535265的博客 1506

莆田市C++专项选拔第一轮题4

现在小明同学想要从两堆硬币中各选择一枚硬币,使得两枚硬币的面值之和 不超过 k。不同的硬币组合,就算面值相同,也视为不同的方案。现在他把这些硬币分成了两堆,已知两堆硬币分别有 n 和 m 枚硬币。可选方案有: (1,2), (1,1), (1,1), (5,2), (5,1), (5,1),共 6 种。第一行三个整数 n, m, k,分别表示第一堆硬币的数量,第二堆硬币的数量,以及面值之和的上限。对于30%的数据,1 ≤ n , m ≤ 1000 , 1 ≤ b , c ≤ 1000。

lpstudio的博客 925

3DGS-to-PC实战指南:零代码实现3D高斯场景到点云/Mesh的高效转换

本文详细介绍了3DGS-to-PC工具如何实现3D高斯场景到点云/Mesh的高效转换,无需代码即可完成。通过实战案例和参数调优技巧,帮助用户快速掌握这一开源插件的使用方法,提升3D数据处理效率。特别适合建筑扫描、影视特效等领域的专业人士。

q1w3e5r7t9y的博客 273

数据结构-双向链表

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点 ...

aaa0329的博客 1万+

Linux ELF文件解析:从file到readelf的完整工具链指南

ELF(可执行与可链接格式)是Linux系统中二进制文件的标准格式,定义了程序加载、内存布局和元数据组织方式。其核心原理在于通过程序头表描述执行视图、节区头表描述链接视图,实现代码与数据的结构化存储。这一格式的技术价值在于为程序调试、安全审计和性能优化提供了底层支持,尤其在动态链接、符号解析和内存保护机制中发挥关键作用。在应用场景上,系统管理员依赖ELF分析工具解决库依赖问题,安全研究员通过检查安全属性评估漏洞风险,开发者则利用反汇编进行代码调试。本文聚焦于file、readelf、objdump等工具链的

weixin_42691065的博客 635

《算法导论》知识点总结

《算法导论》的学习路线: 1.MIT网易公开课《算法导论》,授课老师也是《算法导论》书的作者之一。讲解的内容几乎围绕书籍,不过其中跳跃表和自组织表书中没有,并行算法和缓存参数无关算法还没看。 2.课程配套的笔记,csdn博客:MIT算法导论公开课之课程笔记,可提前看一遍熟悉一下课程内容,这样看视频有重点。 3.看《算法导论》书籍,主要看了前半部分,其中高级数据结构和算法问题选编还没看。 =====...

changfei_1995的博客 1万+

你的小龙虾 OpenClaw 还很笨?快给它装上这几个核心技能(OpenClaw 必装skills整理)

🦞 刚装小龙虾OpenClaw? 本文分享一些OpenClaw必装技能,从视觉理解到智能学习,让它从“会聊天”变“会干活” 🚀

XiaoqiangClub的博客 870

Ultralytics 框架中 model.predict() 返回的 results 对象的详细解析

通过掌握 results 对象的使用方法,您可以快速实现模型部署、数据分析与可视化。

浩瀚之水的专栏 748

阅读《算法导论》的基础要求

熟悉二叉搜索树的性质,即左子树的所有节点值小于根节点值,右子树的所有节点值大于根节点值,并且能够实现二叉搜索树的插入、删除和查找操作,这些操作的平均时间复杂度为 O(log n),但在最坏情况下(树严重不平衡)可能退化为 O(n)。例如,对于分治算法,要能够理解如何将问题分解为较小的子问题,递归地解决子问题,并将子问题的解合并得到原问题的解。坚持和耐心:《算法导论》是一本有一定深度和难度的书籍,阅读过程中可能会遇到很多难以理解的概念和复杂的证明,需要有足够的坚持和耐心,逐步攻克难点,不能轻易放弃。

chinansa的博客 1144

前端使用二开Thingsboard一、二、三事(四)-部件库

以项目实战为基础,逐步介绍前端在thingsboard系统二次开发中的一些注意事项以及一些thingsboard一些页面功能讲解,为前端人员开发使用thingsboard提供一种可靠思路,打造一个完美的物联网系统。

weixin_43163457的博客 739

算法导论记录丨23. 合并 K 个升序链表

过年闲不下来(太菜了多练练),看算法导论书,做一点题目。

LIEBESFREUD的博客 421

在Qt中集成VTK和PCL:实现数据可视化的完整指南

在现代软件开发中,数据可视化至关重要。将VTK(Visualization Toolkit)和PCL(Point Cloud Library)集成到Qt环境里,能为开发者提供强大的可视化解决方案。本文将深入讲解如何在Qt中读取PCL文件,展示VTK模型和PCL数据,适合想要在Qt项目中实现数据可视化的开发者。

轩宇的博客 917

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

算法导论 合并两个链表

合并两个链表1. 算法导论原题 10.2-6 The dynamic-set operation UNION takes two disjoint sets S1 and S2 as input, and it returns a set S = S1 U S2 consisting of all the elements of S1 and S2.The setsS1 andS2 are

梦幻DUO的游戏开发之路 598

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

算法导论 第10章 10.2 链表

一、概念 (1)数组的线性序是由数组的下标决定的,链表中的顺序是由各对象中的指针所决定的 (2)链表结点结构 node *prev; node *next; int key; (3)链表结点 node *head; node *nil;//哨兵 (4)对链表的操作 LIST-SEARCH(L, k) LIST-INSERT(L, x) LIST-DELETE(L, x)

幸福在路上 5413

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

《算法导论》——基本的图算法笔记和部分题解

阿巴阿巴,先写这么多

2301_80489164的博客 2081

单向链表快速排序

第一次在这里发,排版不行,见谅啊,sorry,我就没排版。 对于快速排序,我以前只是用来排数组,从来没有排过链表,直到有一天,我使用了算法导论上 N.Lomoto版本的快速排序,发现这个版本也许可以用来排链表,于是就尝试了下,发现真的可以. 在此先说一下 N.Lomoto 版本和国内普遍使用的 Hoare(霍尔)版本的区别. 霍尔版本应该算是快速排序的正式版本,他改进了之前的算法,然后

gensmusic的专栏 1620

《算法导论》第 10 章 - 基本数据结构

《算法导论》第10章基础数据结构摘要 本文系统讲解了栈、队列、链表和树四种基础数据结构。栈遵循LIFO原则,提供了数组实现及括号匹配等应用案例;队列遵循FIFO原则,展示了循环数组实现和滑动窗口最大值问题。详细介绍了单/双链表的实现,包含节点插入删除等操作,并给出了两数相加的链表应用。在树结构方面,重点讲解了孩子-兄弟表示法及其在文件系统模拟中的应用。所有数据结构均配有完整的C++实现代码、操作流程图和实际应用案例,通过理论与实践结合的方式,帮助读者掌握这些构建复杂算法的基石。

2302_80961196的博客 1394

算法导论(第三版)第一章习题答案

算法导论(第三版)第一章习题答案 这个专栏主要是将算法学习过程中使用的《算法导论》一书的练习题的答案进行汇总,有一部分习题答案可能是我自己做的或者是从网上搜集的,难免会存在错误的地方,希望能得到大家的指正。因为这是初次接触算法,所以后续的章节更新会比较慢,并且可能会出现很多我做不出来的题目,但是会我尽量坚持下去,每天看两页书。码字不易,如果对你有用希望能点个赞,如果有问题欢迎在评论区讨论。 1.1 算法 1-1 生活中需要排序的例子有很多,比如名次,成绩,身高统计等等。 凸壳问题: 令S为平面上的一个点集

越今朝的博客 1519
上一篇: 算法导论之八计数排序
下一篇: 双向链表的C实现
mengrennwpu
博客等级 码龄15年 262粉丝 87原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mengrennwpu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值