链表操作实例(创建节点,增加节点,倒序链表,销毁链表等)

来源:互联网 发布:订单系统数据库设计 编辑:程序博客网 时间:2024/06/10 16:11

链表操作实例

    该实例为:不断输入学生信息(学生姓名,性别,年龄,分数)后,打印输出所有的结果。其中用到了链表的初始化,创建,长度计算,增加节点,倒序链表内容等。这里简单介绍几个重要的链表操作函数。
完整代码下载地址:http://download.csdn.net/download/edroid1530/9671470

    github下载地址:https://github.com/Edroid/student_linklist

一 简要了解

先简单了解一下链表的基础知识
什么是链表,书上给出的定义是:链表由一系列节点(链表中每一个元素称为节点)组成,节点可以在运行时动态生成。每个节点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个节点地址的指针。如图:


我们首先定义一个结构体类型 link_note_t

typedef student_t          Item;typedef struct link_node_s{    Item                   item;    struct  link_node_s    *next;} link_node_t;  /*---  end of struct link_node_s  ---*/

下面我们先来弄清楚几个变量
link_node_t head;  //head为结构体变量,其存放的是结构体内容,我们假设其地址为0x0001
link_node_t *head1;  //head1 为结构体指针变量,其存放的是结构体的地址(0x0001),假设其本身地址为0x0008
link_node_t **head2;  //head2为结构体指针的指针,其存放的是结构体指针变量的地址(0x0008),假设其本身地址为0x000b。

二,链表操作实例

1.统计链表长度,即链表中节点的个数。

int list_item_count(link_node_t *head)  //传入形参为指向结构体的指针{    int              count = 0;    link_node_t      *pnode = head;    if(!head)    //异常处理:如果链表为空,直接返回0        return 0;    while(pnode != NULL)//链表不为空时,计算并返回count的值    {        ++count;        pnode = pnode->next;    }    return count;}

2.增加节点
   向链表中添加新的节点,该其指针域的指针指向的是新的结构体变量
int list_add_item(link_node_t **head, Item item) //传入形参为指向节点的指针和新的结构体变量中的内容{    link_node_t        *pnew; //定义新的结构体指针用来指向新的结构体    link_node_t        *pnode = *head; //定义一个结构体指针用来找到尾节点    pnew = (link_node_t *)malloc(sizeof(*pnew));//开辟新的内存空间用来存放新的节点    if(pnew == NULL)          return -1;      memset(pnew, 0, sizeof(*pnew));//清空pnew,Memset 用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为‘ ’或‘/0’;    pnew->item = item;    if(NULL == *head) //如果第一个节点为空,则将头节点作为新的节点    {        *head = pnew;    }    else //否则,找到链表中最后一个节点并设置其为新的节点    {        while(pnode->next != NULL)        {            pnode = pnode->next;        }        pnode->next = pnew;    }    return 0;}



3.对链表中节点使用函数
void list_traverse(link_node_t *head, void (*pfunc)(Item item)) //传入形参为节点和函数指针{    link_node_t   *pnode = head;    while(pnode != NULL)    {        pfunc(pnode->item);        pnode = pnode->next;    }}
说明:void (*pfunc)(Item item)为函数指针,该函数返回值为空,函数形参为结构体Item中的item


4.倒序链表中的内容
void link_reverse(link_node_t **head){   link_node_t        *revsd_ptr;  /* Last one time reversed linker pointer*/   link_node_t        *cur_ptr;    /* Currently need reverse node pointer*/   link_node_t        *next_ptr;   /* Next need revers node pointer*/   revsd_ptr = NULL;   cur_ptr = *head;   while( cur_ptr != NULL)   {   /* first circulating                             second circulating              * Step1:    * revsd     */ cur  next                                    revsd  cur  next    *         |    |                                   |    |    |    *  NULL   A -> B -> C -> D -> E            NULL <- A    B -> C -> D -> E       next_ptr = cur_ptr->next;   /* Step2:    * revsd   cur  next                             revsd  cur  next    *          |    |                                  |    |    |    *  NULL <- A    B -> C -> D -> E           NULL <- A <- B    C -> D -> E     */       cur_ptr->next = revsd_ptr;   /* Step3:    *         revsd cur/next                             revsd cur/next    *          |      |                                    |     |       * NULL <-  A      B  ->  C -> D -> E      NULL <- A <- B     C -> D -> E    */       revsd_ptr =  cur_ptr;       cur_ptr = next_ptr;   }


5.销毁链表
int list_destroy(link_node_t **head){    link_node_t   *psave;    while( *head )//当节点不为NULL时    {        psave = (*head)->next;        free(*head);  //释放内存        *head = psave;    }}

关于什么时候形参为节点(link_note_t *head),什么时候形参为节点地址(link_note_t **head) 的问题:
  
刚开始学链表的时候最难理解的地方就是形参的确定,不妨对比一下经典的swap函数
void swap(int *a, int *b){   int c;   c = *a;   *a = *b;   *b =*a;}int main(void){  int a = 2,b = 3;  swap(&a,&b);  printf("%d,%d\n",a,b)}
只有给swap传入a, b 的地址的时候才能真正改变其内容本身,如果只是传入变量a,b本身,swap函数中改变的是形参也就是swap中的局部变量,并没有改变a,b本身的内容。对比一下就会发现,其实链表的操作也是一样的,如果涉及到链表本身内容的改变,我们需要传入节点的地址,即 link_note_t **head,如果不改变链表内容本身,则传入节点 link_note_t *head。


本人能力有限,以上只是个人学习链表之后的一个总结和看法,难免有错误之处。若发现错误欢迎指正,感激不尽。




0 0
原创粉丝点击