• 单向列表的实现代码,以及注释解释笔记


     1 *define a structure for linked lists*/
     2 /*这里定义了一个list链表的类型*/
     3 
     4 typedef struct List_
     5 {
     6     int size;
     7     int (*match)(const void *key1,const void *key2);
     8     void (*destroy)(void *data);
     9     ListElmt *head;                      //head指向链表头结点的指针
    10     ListElmt *tail;                      //tail是指向链表中末尾的元素的指针
    11 }List;
    12 
    13 
    14 
    15 /*public interface*/
    16 
    17 void list_init(List *list,void(*destroy)(void *data));      //链表初始化的,或者说创建的函数定义;
    18 void list_destroy(List *list);                             // 链表数据结构的析构函数的定义;
    19 int list_ins_next(List *list,ListElmt *element,const void *data);       //在list指定的的链表的element元素后面插入一个元素值data,if true return0;else return -1;
    20 int list_rem_next(List *list,ListElmt *element,const void **data);   //在list指定的链表元素element元素后面移除一个元素值data,返回值同上;
    21 
    22 /*下面是预先定义的宏*/
    23 #define list_size(list) ((list)->size)     //链表中元素的个数
    24 #define list_head(list) ((list)->head)    //链表中的头元素的指针
    25 #define list_tail(list) ((list)->tail);   //链表中末尾元素的指针
    26 #define list_is_head(list,element) ((element) == (list)->head ?1:0)    //判断元素是不是头元素
    27 #define list_is_tail(element) ((element)->next==NULL ?1:0)            //判断元素是不是最后一个元素
    28 #define list_data(element) ((element)->data)                   //结点的数据
    29 #define list_next(element) ((element)->next)                   //下一个元素的指针
    30 
    31 
    32 #endif

    上面是单项列表的实现的头文件,定义了各种接口,以及元素结点,链表结构。

    下面是单项列表实现的过程。

      1 include "list.h"
      2 
      3 #include<stdlib.h>
      4 #include<stdio.h>
      5 #include<string.h>
      6 
      7 
      8 //list_init
      9 void list_init(List *list,void (*destroy)(void *data)){
     10          //初始化这个列表
     11          list->size=0;
     12          list->destroy =destroy;
     13          list->head=NULL;
     14          list->tail=NULL;
     15 
     16 
     17          return;
     18 }
     19 
     20 
     21 
     22 //list_destroy
     23 
     24 void list_destroy(List *list){
     25           void *data;
     26                                          //下面移除掉链表里的每一个元素
     27           while(list_size(list)>0){
     28                  if(list_rem_next(list,NULL,(const void **)&data)==0 && list->destroy!=NULL){
     29                                    list->destroy(data);       //引用一个用户定义的函数去释放申请的内存空间
     30                                 }
     31                           }
     32 memset(list,0,sizeof(data));//没有运算被允许,但是要清空结构作为预处理
     33 return;
     34 }
     35 
     36 
     37 //list_ins_next
     38 
     39 int list_ins_next(List *list,ListElmt *element,const void *data){
     40               ListElmt *new_element;
     41               if((new_element=(ListElmt *)malloc(sizeof(ListElmt)))==NULL){
     42                 return -1;             /*如果内存申请失败,则返回-1,这里把新结点的内存申请放在判断条件里进行了*/
     43               }
     44               new_element->data=(void*)data;   //把要插入的元素值赋给新的位置
     45               if(element==NULL){               //要插入位置的元素不为空的话
     46                 if(list_size(list)==0){          //如果链表的大小为0,那么把要插入的元素,直接给到链表的末尾,最后一个
     47                   list->tail==new_element;
     48 
     49                   new_element->next=list->head;    //把这个元素结点的下一个地址赋值给链表头元素
     50                   list->head=new_element;          //链表的头元素,就是这个新插入的元素成员
     51                 }
     52               }
     53               else{                                    //如果这个要插入的位置的元素不为空
     54                 if(element->next==NULL){                //判断这个插入位置是不是最后一个,
     55                   list->tail=new_element;               //如果是最后一个的话,把要插入的结点放在最后
     56                   new_element->next=element ->next;     //新插入的结点的指向本位置下一个元素的指针
     57                   element->next=new_element->next;     //插入位置的元素的指针指向新插入的元素
     58                 }
     59               }
     60 
     61               list->size++;       //插入成功以后,给链表的大小加上一
     62     return 0;
     63 }
     64 
     65 
     66 
     67 //list_rem_next
     68 int list_rem_next(List *list,ListElmt *element,const void **data){
     69          ListElmt *old_element;
     70 
     71          if(list_size(list)==0){
     72               return -1;                        /*如果给定的列表为空表的话,直接返回-1*/
     73          }
     74          if(element==NULL)                      //如果要删除的位置为NULL的话,执行
     75              {
     76                *data=list->head->data;             //数据等于链表头的元素值
     77                old_element =list->head;             //把链表头元素地址给old_element
     78                list->head=list->head->next;         //链表头结点移动到下一个元素结点
     79 
     80                if(list_size(list)==1){
     81                  list->tail=NULL;                      //如果只有一元素的话,末尾的结点指向空指针
     82                }
     83              }
     84          else
     85            {                                              //如果删除的位置不为空
     86             if(element->next==NULL){
     87               return -1;
     88             }
     89             *data=element->next->data;
     90             old_element=element->next;
     91             element->next=element->next->next;
     92             if(element->next==NULL)
     93             list->tail=element;
     94            }
     95     free(old_element);                                //删除结束后把不需要的结点从内存释放掉
     96     list->size--;       //链表的大小减一
     97     return 0;
     98 }
     99 
    100 
    101 
    102 int main(void){
    103        printf("end");
    104        return 0;
    105 }

    最后面的main函数是为了,编译成功执行一下子。

    如果是使用链表的话,尽量把实现的代码,放在单独的c文件里。

  • 相关阅读:
    [POI2011]Lightning Conductor
    [NOI2009]诗人小G

    公告&留言板
    联合省选 2020 题解
    年末时的一些思维碎屑
    RE:ゼロから始める AFO 生活
    退役前的做题记录6.0
    2019年湖南省大学生计算机程序设计竞赛 (HNCPC2019) 简要题解
    300iq Contest 1 简要题解
  • 原文地址:https://www.cnblogs.com/BlogOfMr-Leo/p/9025142.html
Copyright © 2020-2023  润新知