Linux C语言实现-------双向链表

1 前言: 前几天写过一篇单链表逆序的文章点击打开链接, 本来准备第二天就把双向链表方便的东西补全的, 

奈何公(懒)务(癌)缠(发)身(作) , 拖到现在。

2 什么是链表 


老规矩 , 先上一副数据结构的图 , 希望大家加深理解

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序通过链表中的指针链接次序实现。链表由一系列存储结点组成,结点可在运行时动态生成。每个结点均由两部分组成,即存储数据元素的数据域和存储相邻结点地址的指针域。当进行插入或删除操作时,链表只需修改相关结点的指针域即可,因此相比线性表顺序结构更加方便省时。

     链表可分为单链表(Singly Linked List)、双向链表(Doubly Linked List)和循环链表(Circular List)等。一个单链表结点仅包含一个指向其直接后继结点的指针,因此当需要操作某个结点的直接前驱结点时,必须从单链表表头开始查找。

     双向链表和循环链表均为单链表的变体。通常创建双向循环链表以综合利用两者的优点。

2.1 双向链表

双向链表的节点 , 除了有数据域之外 ,还有两个指针域, 分别指向该节点的前驱节点和后继节点,因此, 从双向链表中任意位置开始 , 都能很方便得访问其前驱和后继节点 ,  节点如图1

                    

                        图1  双向链表节点

如图1所示 , Data为该节点的数据域,prev指向直接前驱节点, 而next指向直接后继节点,通常, 双向链表会含有一个表头(也称作哨兵节点),  它的作用是能够迅速定位到链表头的位置, 简化我们对链表的任何操作包括但不限于增加,删除,遍历,查找等等操作, 双向有头非空链表结构如下图2

                

                    图2 双向有头非空链表

图中表头节点dhead的prev指向空,  C节点的next指向空, 除表头节点和尾节点外, 链表中任意节点都满足以下关系

                p = p->next->prev = p->prev->next 

也就是 , 当前节点的前驱的后继是当前节点 ,   当前节点的后继的前驱也是当前节点,  虽然有点拗口 , 但是请大家要记住。


3 双向循环链表实现:

3.1插入

假设指针p和q指向双向链表中的两个前后相邻结点,将某个新结点(指针为s)插到p和q之间,其过程及C语言描述如下图所示图3:


        图3 双向链表插入过程

请大家注意 , 插入顺序不具备唯一性 , 但是为了保证链接的完整 , 第四步操作一定要是p->next 或 q->prev,不然会丢失掉P的后继或者是q的前驱 , 这里要一定要注意,总结下伪代码如下:

s->prev = p;
s->next = q;
q->prev = s;
p->next = s;

3.2 删除

删除也就是插入的逆向操作 , 如上图, s节点成功插入到链表中, 我们删除也只需改变s节点的前驱和后继指针的指向 ,  再释放掉s节点申请的内存就行了, 伪代码如下:

p->next = s->next;
q->prev = s->prev;
free(s->data);
free(s);

3.3 查找

查找也就是从头节点开始, 遍历整张表, 遍历的时候逐一比对数据域的值就行了

代码如下:

llist.h

#ifndef ___LLIST_H__
#define ___LLIST_H__

#include <stdio.h>
#include <string.h> 
#include <stdlib.h>
    
//定义函数指针

typedef void (llist_op_t)(void *);
typedef int (llist_cmp_t)(void *, void *);
    
    
//获取字符串
#define GETLINES(string, buf) do{                           \
                        printf(string);                     \
                        fgets(buf, sizeof(buf), stdin);     \
                        if (buf[strlen(buf) - 1] == '\n')   \
                            buf[strlen(buf) - 1] = '\0';    \
                    }while(0)


//
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值