Linux C 数据结构---链表(单向链表)

 上一篇我们讲到了线性表,线性表就是数据元素都一一对应,除只有唯一的前驱,唯一的后继。

       线性表存储结构分为顺序存储、链式存储。

       顺序存储的优点:

       顺序存储的缺点:

       链表就是典型的链式存储,将线性表L = (a0,a1,a2,........an-1)中个元素分布在存储器的不同存储块,成为结点(Node),通过地址或指针建立他们之间的练习,所得到的存储结构为链表结构。表中元素ai的结点形式如下:

其中,结点的data域存放数据元素ai,而next域是一个指针,指向ai的直接后继a(i+1)所在的结点。于是,线性表L=(a0,a1,......an-1)的结构如图:

 

一、节点类型描述:

[cpp]  view plain   copy
  1. typedef struct node_t  
  2. {  
  3.     data_t data; //节点的数据域  
  4.     struct node_t *next;//节点的后继指针域  
  5. }linknode_t,*linklist_t;  

也可这样表示:

[cpp]  view plain   copy
  1. struct node_t  
  2. {  
  3.     data_t data;   
  4.     struct node_t *next;  
  5. }  
  6. typedef struct node_t linknode_t;  
  7. typedef struct node_t *linklist_t;  

若说明

linknode_t  A;

linklist_t p  = &A;

则结构变量A为所描述的节点,而指针变量P为指向此类型节点的指针(p的值为节点的地址);

这样看来 linknode_t  linklist_t 的作用是一样的,那为什么我们要定义两个数据类型(同一种)呢?主要为了代码的可读性,我们要求标识符要望文识义,便于理解;

1、linknode_t  *pnode  指向一个节点;

2、linklist_t list  指向一个整体


二、头结点 head

        我们在前篇提到的顺序存储线性表,如何表达一个空表{ },是通过list->last = -1来表现的,所谓的空表就是数据域为NULL,而我们的链表有数据域和指针域,我们如何表现空链表呢?这时,就引入了头结点的概念,头结点和其他节点数据类型一样,只是数据域为NULL,head->next = NULL,下面我们看一个创建空链表的函数,如何利用头结点来创建一个空链表:

[cpp]  view plain   copy
  1. linklist_t CreateEmptyLinklist()  
  2. {  
  3.     linklist_t list;  
  4.   
  5.     list = (linklist_t)malloc(sizeof(linknode_t));  
  6.     if (NULL != list) {  
  7.         list->next = NULL;  
  8.     }  
  9.     return list;  
  10. }  

只要头结点,链表就还在!

 

三、链表基本运算的相关算法

         链表的运算除了上面的创建空链表,还有数据的插入,删除,查找等函数,链表的运算有各种实现方法,如何写出一个高效的,封装性较好的函数是我们要考虑的,比如数据插入函数,我们就要尽可能考虑所有能出现的结果,比如:1)如果需插入数据的链表是个空表;2)所插入的位置超过了链表的长度;如果我们的函数能包含所有能出现的情况,不仅能大大提高我们的开发效率,也会减少代码的错误率。下面,我们来看看下面的这个链表的插入函数的实现:

[cpp]  view plain   copy
  1. int InsertLinklist(linklist_t list, int at, data_t x)  
  2. {  
  3.     linknode_t *node_prev, *node_at, *node_new;  
  4.     int pos_at;  
  5.     int found = 0;  
  6.   
  7.     if (NULL == list) return -1;  
  8.   
  9.     /* at must >= 0  */  
  10.     if (at < 0) return -1;  
  11.       
  12.     /*第一步、分配空间*/  
  13.     node_new = malloc(sizeof(linknode_t));  
  14.     if (NULL == node_new)   
  15.     {  
  16.         return -1;  
  17.     }  
  18.     node_new->data = x; /* assigned value */  
  19.     node_new->next = NULL; /*节点如果插入超过链表长度的位置,会接到尾节点后面,这样,node_new成了尾节点,node_new->next = NULL */  
  20.   
  21.     /*第二步、定位*/  
  22.     node_prev = list;//跟随指针,帮助我们更好的定位  
  23.     node_at = list->next; //遍历指针  
  24.     pos_at = 0;  
  25.     while (NULL != node_at)   
  26.     {  
  27.         if (pos_at == at)  
  28.         {  
  29.             found = 1; //找到正确的位置,跳出循环  
  30.             break;            
  31.         }  
  32.   
  33.         /* move to the next pos_at */  
  34.         node_prev = node_at; //跟随指针先跳到遍历指针的位置  
  35.         node_at = node_at->next;//遍历指针跳到下一个节点的位置  
  36.         pos_at++;  
  37.     }  
  38.   
  39.     /*第三步、插入*/    
  40.     if (found)   
  41.     {  
  42.         /* found = 1,找到正确的位置,插入  */  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值