正在加载内容…
附录对于头结点单向链表的优化方法
720 字
4 分钟
附录对于头结点单向链表的优化方法
本文介绍无头结点单向链表的优化:用栈上dummy节点临时充当头结点,遍历或增删结束后还原header指针,使结构统一,并给出初始化、插入、删除及销毁实现。
————————————本文旨在交流学习计算机知识,欢迎交流讨———————————
上一章,我们浅显的讨论了链表的结构,本文在上一章的链表的基础上做出了些许优化,可配合食用。
回到正题,我们已经了解链表的结构,它是一种非连续空间存储的线性表,主要依靠地址域访问下一个元素并通过遍历操作进行增删改查。
如图,这是我们上一章所介绍的链表结构:
我们的惯用操作:
//单向链表的插入,删除(先找到节点p):
//插入:newnode->next=p->next;p->next=newnode;//删除:node_new temp;temp=p->next;p->next=p->next->next;free(temp);看着这幅图,我们不禁想到一个问题:我们真的需要这个头节点吗,是否有些看起来不整齐且结构不一致?于是,我们考虑到:也许我们可以用指针标记header的位置,然后再在每一次的函数接口里面新建一个头结点,用完即删,这样或许看起来更加的整齐和高效。
如图所示:
这时,我们引入dummy节点,并将其放入栈,dummy节点充当第一个节点。
void insert(link*header,element val){node_t dummy;dummy->next=header;//header为我们的指针(因为简化了头结点,我们只传入指针)node_t *p=&dummy;//p为遍历指针,从dummy开始遍历;while(p->next){p=p->next;}header=dummy->next;//还原操作;}下面,我们重写一下代码: 定义链表结构:
typedef int Element_t;struct node{Element_t val;struct node *next;}node_t;//节点的结构体;
typedef struct {node_t *header;int count;} List_t;//链表结构体(包括头结点和数量);初始化链表:
void initList(List_t *table){table->count=0;table->header=NULL;)从最基础的展现函数开始:
void shouList(const List_t *table){node_t p=table->header;printf("List :");while(p){printf("%d\t",p->val);p=p->next;}printf("\n");}这里如果不知道const为什么要放在形参里的可以看看我的第一篇文章,里面有详细解答。 然后就是增删改查的经典案例了: 从增开始:
int insertListHeader(List_t* table,Element_t val){node_t dummy;dummy.next=table->header;
node_t *p=&dummy;//临时头结点dummy及临时过渡中间容器p;node_t *new_node=malloc(sizeof(node_t));
if(new_node==NULL){printf("ERROR\n");)//朴素的增加操作;new_node->val=val;new_node->next=p->next;p->next=new_node;++table->count;
table->header=dummy->next;return 0;}然后这是按位插入操作:
int insertListPos(List_t* table,int pos,Element_t val){if(postable->count){printf("the pos is not a truly place\n");}node_t dummy;dummy.next=table->header;node_t* p=&dummy;int index=-1;//计数器;while(indexnext;++index;}//遍历查找node_t *new_node=malloc(sizeof(node_t));new_node->next=p->next;p->next=new_node;++table->count;table->header=dummy.next;return 0;}删除操作:
int deleteList(List_t* table,Element val){node_t dummy;dummy.next=table->header;
node_t* p=&dummy;while(p->next&&p->val!=val){p=p->next;}if(p->next==NULL){printf("404 NOT FOUND\n");return 0;}node_t temp=malloc(sizeof(node_t));temp=p->next;p->next=p_next_next;free(temp);--table->count;table->header=dummy->next;return 0;}最后的最后就是销毁链表了 : ###关于销毁链表,其原理就是按位遍历并按位删除。###
void destroyList(List_t *table) {node_t dummy;dummy.next = table->header;
node_t *p = &dummy;node_t *tmp;while (p->next) {tmp = p->next;p->next = tmp->next;free(tmp);--table->count;}printf("LinkList have %d node!\n", table->count);// table->header = NULL;}以上就是附录内容,欢迎指正!
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
附录对于头结点单向链表的优化方法
https://mjzy.tech/posts/knowledge/附录对于头结点单向链表的优化方法/ 相关文章 智能推荐
1
拓展单向循环链表
数据结构 本文讲解单向循环链表的C语言实现,先分析带头结点与尾指针的结构设计,再给出初始化、头插、尾插、删除、遍历和销毁函数。边界是仅讨论实现思路,未展开约瑟夫环测试。
2
链表的实现与介绍
数据结构 本文介绍链表的结构与C语言实现,针对顺序表内存碎片问题引出链式存储。讲解节点数据域与地址域,给出初始化、按位插入、按值删除及遍历等函数代码。讨论限于无操作系统内存分配场景。
3
链表最终章双向链表及其应用
数据结构 本文讲解带头节点的双向循环链表,用静态函数封装插入与删除,并实现初始化、头尾插、查找删除、展示和销毁,说明双向结构虽增加代码复杂度但操作更便捷。
4
顺序表的实现与介绍及部分工程思想的思考
数据结构 本文介绍堆空间动态顺序表的实现,含表头data、pos、capacity,用malloc和free管理,扩容两倍并搬移数据,讨论插入删除的搬移逻辑与防泄露的工程思想,并以测试验证。
5
数据结构之树及树的存储
数据结构 本文介绍树的基本概念与存储表示法:双亲表示法找父节点快、找孩子需遍历;孩子表示法相反;孩子兄弟表示法用二叉链表存左孩子右兄弟,便于查孩子和兄弟。
随机文章 随机推荐
评论区
正在加载 GitHub 评论…