单向链表的C语言实现与基本操作

本文的主要内容目录:

一、单向链表的C语言实现

二、单向链表的基本操作


一、单向链表的C语言实现

链表作为一种基本的数据结构在程序开发过程当中经常会使用到。对C语言来说链表的实现主要依靠结构体和指针,所以本文相关内容和程序需要有C语言当中指针和结构体的基础。

链表是一种线性存储数据的结构,存储内容在逻辑上连续的,在物理上却不一定连续。单向链表的组成包括一个链表头(head)和若干链表元素(node),对链表的基本操作其实就是增、删、改、查。

首先说说单向链表的C语言实现方法。为了实现一个单向链表,首先定义一个结构体:

  1. /* 定义一个表示链表的结构体指针 */  
  2. struct list {  
  3.     int id;         /* 标识这个元素方便查找 */  
  4.     char data[20];      /* 链表中包含的元素 */  
  5.     struct list *next;  /* 指向下一个链表的指针 */  
  6. };  
/* 定义一个表示链表的结构体指针 */
struct list {
    int id;         /* 标识这个元素方便查找 */
    char data[20];      /* 链表中包含的元素 */
    struct list *next;  /* 指向下一个链表的指针 */
};
下面来编写程序实现一个链表的基本操作。该程序的功能是首先分配若干个链表元素(node),然后对这些链表元素进行赋初值,赋完初值之后将这些链表元素依次加入到链表当中,最后把这些元素的data字段依次打印出来。(注意 :本程序实现的链表头结点(head)当中是存放数据的;为了保证每一个元素的id字段都不相同,所以定义了一个全局静态数据成员list_id;使用linux下的gcc进行编译)。程序如下:

扫描二维码关注公众号,回复: 1509701 查看本文章
  1. /* 包含的头文件 */  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4.   
  5. /* 定义一个表示链表的结构体指针 */  
  6. struct list {  
  7.     int id;         /* 标识这个元素方便查找 */  
  8.     char data[20];      /* 链表中包含的元素 */  
  9.     struct list *next;  /* 指向下一个链表的指针 */  
  10. };  
  11.   
  12. /* 定义一个链表头部 */  
  13. static struct list *list_head = NULL;  
  14.   
  15. /* 为了保证每一个链表元素的id不同,特意把id定义成一个全局静态变量 */  
  16. static int list_id = 0;  
  17.   
  18. /** 将指定元素插入到聊表尾部 
  19.   *     head    : 表示要插入元素的链表的头部的地址 
  20.   * list    : 表示要插入到链表中的元素 
  21.   */  
  22. static void list_add(struct list **head, struct list *list)  
  23. {  
  24.     struct list *temp;  
  25.   
  26.     /* 判断链表是否为空 */  
  27.     if(NULL == *head)  
  28.     {  
  29.         /* 为空 */  
  30.         *head = list;  
  31.         (*head)->next = NULL;  
  32.     }  
  33.     else  
  34.     {  
  35.         /* 不为空 */  
  36.         temp = *head;  
  37.         while(temp)  
  38.         {  
  39.             if(NULL == temp->next)  
  40.             {  
  41.                 temp->next = list;  
  42.                 list->next = NULL;  
  43.             }  
  44.             temp = temp->next;  
  45.         }  
  46.     }  
  47. }  
  48.   
  49. /** 遍历一个链表,打印链表中每个元素所包含的数据 
  50.   * head : 表示要遍历的链表的头部的指针 
  51.   */  
  52. static void list_print(struct list **head)  
  53. {     
  54.     struct list *temp;  
  55.   
  56.     temp = *head;  
  57.   
  58.     printf(”list information :\n”);  
  59.     while(temp)  
  60.     {  
  61.         printf(”\tlist %d : %s\n”, temp->id, temp->data);  
  62.         temp = temp->next;  
  63.     }  
  64. }  
  65.   
  66. /* 主函数,程序的入口 */  
  67. int main(int argc, char *argv[])  
  68. {  
  69.     int i = 0;  
  70.     struct list *lists = NULL;  
  71.   
  72.     /* 分配10个元素 */  
  73.     lists = malloc(sizeof(struct list) * 10);  
  74.     if(NULL == lists)  
  75.     {  
  76.         printf(”malloc error!\n”);  
  77.         return -1;  
  78.     }  
  79.   
  80.     /* 将分配的10个元素依次填充数据并加入到链表当中 */  
  81.     for(i = 0; i < 10; i++)  
  82.     {  
  83.         lists[i].id = list_id++;  
  84.         sprintf(lists[i].data, ”TECH-PRO - %d”, i);  
  85.   
  86.         list_add(&list_head, &lists[i]);  
  87.     }  
  88.   
  89.     /* 遍历链表,把链表中每个元素的信息都打印出来 */  
  90.     list_print(&list_head);  
  91.   
  92.     return 0;  
  93. }  
/* 包含的头文件 */




include <stdio.h>

include <stdlib.h>

/* 定义一个表示链表的结构体指针 */
struct list {
int id; /* 标识这个元素方便查找 */
char data[20]; /* 链表中包含的元素 */
struct list next; / 指向下一个链表的指针 */
};

/* 定义一个链表头部 */
static struct list *list_head = NULL;

/* 为了保证每一个链表元素的id不同,特意把id定义成一个全局静态变量 */
static int list_id = 0;

/** 将指定元素插入到聊表尾部
* head : 表示要插入元素的链表的头部的地址
* list : 表示要插入到链表中的元素
*/
static void list_add(struct list **head, struct list *list)
{
struct list *temp;

/* 判断链表是否为空 */
if(NULL == *head)
{
    /* 为空 */
    *head = list;
    (*head)-&gt;next = NULL;
}
else
{
    /* 不为空 */
    temp = *head;
    while(temp)
    {
        if(NULL == temp-&gt;next)
        {
            temp-&gt;next = list;
            list-&gt;next = NULL;
        }
        temp = temp-&gt;next;
    }
}

}

/** 遍历一个链表,打印链表中每个元素所包含的数据
* head : 表示要遍历的链表的头部的指针
*/
static void list_print(struct list **head)
{
struct list *temp;

temp = *head;

printf("list information :\n");
while(temp)
{
    printf("\tlist %d : %s\n", temp-&gt;id, temp-&gt;data);
    temp = temp-&gt;next;
}

}

/* 主函数,程序的入口 */
int main(int argc, char *argv[])
{
int i = 0;
struct list *lists = NULL;

/* 分配10个元素 */
lists = malloc(sizeof(struct list) * 10);
if(NULL == lists)
{
    printf("malloc error!\n");
    return -1;
}

/* 将分配的10个元素依次填充数据并加入到链表当中 */
for(i = 0; i &lt; 10; i++)
{
    lists[i].id = list_id++;
    sprintf(lists[i].data, "TECH-PRO - %d", i);

    list_add(&amp;list_head, &amp;lists[i]);
}

/* 遍历链表,把链表中每个元素的信息都打印出来 */
list_print(&amp;list_head);

return 0;

} 程序的运行结果如下所示:


二、单向链表的基本操作

链表的基本操作其实就是对链表中元素的操作。链表的基本操作包括链表中结点元素的添加、删除、修改和查看,简单来说就是增、删、改、查。

2.1 单向链表中元素添加

在链表中添加元素时首先判断链表是否为空,为空时直接把要添加的元素赋值给链表头部,否者就要对链表进行遍历找到下一个为空的结点,然后把元素插入到链表尾部。

实现链表插入的程序代码:

  1. /** 将指定元素插入到聊表尾部 
  2.   *     head    : 表示要插入元素的链表的头部的地址 
  3.   * list    : 表示要插入到链表中的元素 
  4.   */  
  5. static void list_add(struct list **head, struct list *list)  
  6. {  
  7.     struct list *temp;  
  8.   
  9.     /* 判断链表是否为空 */  
  10.     if(NULL == *head)  
  11.     {  
  12.         /* 为空 */  
  13.         *head = list;  
  14.         (*head)->next = NULL;  
  15.     }  
  16.     else  
  17.     {  
  18.         /* 不为空 */  
  19.         temp = *head;  
  20.         while(temp)  
  21.         {  
  22.             if(NULL == temp->next)  
  23.             {  
  24.                 temp->next = list;  
  25.                 list->next = NULL;  
  26.             }  
  27.             temp = temp->next;  
  28.         }  
  29.     }  
  30. }  
/**    将指定元素插入到聊表尾部
  *     head    : 表示要插入元素的链表的头部的地址
  * list    : 表示要插入到链表中的元素
  */
static void list_add(struct list **head, struct list *list)
{
    struct list *temp;

    /* 判断链表是否为空 */
    if(NULL == *head)
    {
        /* 为空 */
        *head = list;
        (*head)->next = NULL;
    }
    else
    {
        /* 不为空 */
        temp = *head;
        while(temp)
        {
            if(NULL == temp->next)
            {
                temp->next = list;
                list->next = NULL;
            }
            temp = temp->next;
        }
    }
}
在main函数中田间如下代码:
  1. struct list temp_list;  
  2.   
  3. /* 填充这个结构体并加入链表当中 */  
  4.     temp_list.id = list_id++;  
  5.     sprintf(temp_list.data, ”temp_list”);  
  6.     list_add(&list_head, &temp_list);  
struct list temp_list;

/* 填充这个结构体并加入链表当中 */
    temp_list.id = list_id++;
    sprintf(temp_list.data, "temp_list");
    list_add(&list_head, &temp_list);
对程序进行编译,结果如下:

2.2 在单向链表中删除元素

在链表删除一个元素结点是链表基本操作中相对复杂的。首先需要判断链表是否为空,当链表不为空时,要再次判断要删除的元素是否是头结点(head),如果是直接将下一个元素赋值给头结点,不过不是就需要遍历整个链表找到要删除的结点元素。(注:本算法实现的删除是通过对元素结点的id字段进行的)。

删除链表结点的程序代码:

  1. /** 将指定元素从链表尾部删除 
  2.   *     head    : 表示要删除元素的链表的头部的地址 
  3.   * id      : 表示要删除元素的标识 
  4.   * 返回值  : 0-成功,-1-失败 
  5.   */  
  6. static int list_del(struct list **head, int id)  
  7. {  
  8.     struct list *temp, *p;  
  9.     temp = *head;  
  10.   
  11.     if(NULL == temp)  
  12.     {  
  13.         /* 链表为空 */  
  14.         printf(”链表为空!\n”);  
  15.         return -1;  
  16.     }  
  17.     else  
  18.     {  
  19.         /* 判断匹配的元素是否为链表头部的元素 */  
  20.         if(id == temp->id)       /* 是链表头部 */  
  21.         {  
  22.             *head = temp->next;  
  23.             return 0;  
  24.         }  
  25.         else                    /* 不是链表头部 */  
  26.         {  
  27.             while(temp->next)  
  28.             {  
  29.                 p = temp;  
  30.                 temp = temp->next;  
  31.   
  32.                 if(id == temp->id)  
  33.                 {  
  34.                     p->next = temp->next;  
  35.                     return 0;  
  36.                 }  
  37.             }     
  38.             return -1;  
  39.         }  
  40.     }  
  41.   
  42.     return -1;  
  43. }  
/**   将指定元素从链表尾部删除
  *     head    : 表示要删除元素的链表的头部的地址
  * id      : 表示要删除元素的标识
  * 返回值  : 0-成功,-1-失败
  */
static int list_del(struct list **head, int id)
{
    struct list *temp, *p;
    temp = *head;

    if(NULL == temp)
    {
        /* 链表为空 */
        printf("链表为空!\n");
        return -1;
    }
    else
    {
        /* 判断匹配的元素是否为链表头部的元素 */
        if(id == temp->id)       /* 是链表头部 */
        {
            *head = temp->next;
            return 0;
        }
        else                    /* 不是链表头部 */
        {
            while(temp->next)
            {
                p = temp;
                temp = temp->next;

                if(id == temp->id)
                {
                    p->next = temp->next;
                    return 0;
                }
            }   
            return -1;
        }
    }

    return -1;
}
在main函数中添加如下代码:
  1. /* 删除链表中开始位置、中间位置、尾部的元素 */  
  2.     list_del(&list_head, 0);  
  3.     list_del(&list_head, 5);  
  4.     list_del(&list_head, 10);  
/* 删除链表中开始位置、中间位置、尾部的元素 */
    list_del(&list_head, 0);
    list_del(&list_head, 5);
    list_del(&list_head, 10);
对程序进行编译结果如下所示,第0、5、10号元素都被删除:


2.3 在单向链表中修改指定的元素

在链表中修改元素,通过对链表中元素进行遍历,找到要修改的元素对其内容分进行修改即可,实现链表元素的修改是相对容易的。(注 :对要修改的元素的定位是通过id字段来完成的)

链表中修改元素的程序如下:

  1. /** 将指定id的元素所定义的内容进行修改 
  2.   *     head    : 表示要改变元素的链表的头部的地址 
  3.   * id      : 表示要改变元素的标识 
  4.   * content : 表示要改变的内容 
  5.   * 返回值  : 0-成功,-1-失败 
  6.   */  
  7. static int list_chg(struct list **head, int id, char *content)  
  8. {  
  9.     struct list *temp;  
  10.   
  11.     temp = *head;   /* 将链表的头部赋值给临时聊表变量 */  
  12.   
  13.     while(temp)     /* 对链表进行轮询 */  
  14.     {  
  15.         if(id == temp->id)  
  16.         {  
  17.             memset(temp->data, 0, sizeof(temp->data));  
  18.             sprintf(temp->data, ”%s”, content);  
  19.             temp->data[strlen(content)] = ’\0’;  
  20.             return 0;  
  21.         }  
  22.         temp = temp->next;  
  23.     }  
  24.     return -1;  
  25. }  
/**   将指定id的元素所定义的内容进行修改
  *     head    : 表示要改变元素的链表的头部的地址
  * id      : 表示要改变元素的标识
  * content : 表示要改变的内容
  * 返回值  : 0-成功,-1-失败
  */
static int list_chg(struct list **head, int id, char *content)
{
    struct list *temp;

    temp = *head;   /* 将链表的头部赋值给临时聊表变量 */

    while(temp)     /* 对链表进行轮询 */
    {
        if(id == temp->id)
        {
            memset(temp->data, 0, sizeof(temp->data));
            sprintf(temp->data, "%s", content);
            temp->data[strlen(content)] = '\0';
            return 0;
        }
        temp = temp->next;
    }
    return -1;
}
在main函数中添加如下代码:
  1. /* 改变id为4的元素所对应的值为 “change!!!” */  
  2.     list_chg(&list_head, 4, ”change!!!”);  
/* 改变id为4的元素所对应的值为 "change!!!" */
    list_chg(&list_head, 4, "change!!!");
编译程序,运行结果如下所示:


2.4 对单向链表的元素进行查询操作

在链表中查询一个元素,根据链表头部对链表进行遍历即可。

链表中查询的程序代码:

  1. /** 将指定id的元素所定义的内容进行查找 
  2.   *     head    : 表示要查询元素的链表的头部的地址 
  3.   * id      : 表示要查询元素的标识 
  4.   * 返回值  : 0-成功,-1-失败 
  5.   */  
  6. static int list_query(struct list **head, int id)  
  7. {  
  8.     struct list *temp;  
  9.   
  10.     temp = *head;   /* 将链表的头部赋值给临时聊表变量 */  
  11.   
  12.     while(temp)     /* 对链表进行轮询 */  
  13.     {  
  14.         if(id == temp->id)  
  15.         {  
  16.             printf(”list %d : %s\n”, temp->id, temp->data);  
  17.             return 0;  
  18.         }  
  19.         temp = temp->next;  
  20.     }  
  21.   
  22.     /* 没有找到元素 */  
  23.     printf(”not finding!\n”);  
  24.       
  25.     return -1;  
  26. }  
/** 将指定id的元素所定义的内容进行查找
  *     head    : 表示要查询元素的链表的头部的地址
  * id      : 表示要查询元素的标识
  * 返回值  : 0-成功,-1-失败
  */
static int list_query(struct list **head, int id)
{
    struct list *temp;

    temp = *head;   /* 将链表的头部赋值给临时聊表变量 */

    while(temp)     /* 对链表进行轮询 */
    {
        if(id == temp->id)
        {
            printf("list %d : %s\n", temp->id, temp->data);
            return 0;
        }
        temp = temp->next;
    }

    /* 没有找到元素 */
    printf("not finding!\n");

    return -1;
}
程序运行结果:



附录:单向链表的基本操作已经说完,附上一个完整的程序。

  1. /* 包含的头文件 */  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <string.h>  
  5.   
  6. /* 定义一个表示链表的结构体指针 */  
  7. struct list {  
  8.     int id;             /* 标识这个元素方便查找 */  
  9.     char data[20];      /* 链表中包含的元素 */  
  10.     struct list *next;  /* 指向下一个链表的指针 */  
  11. };  
  12.   
  13. /* 定义一个链表头部 */  
  14. static struct list *list_head = NULL;  
  15.   
  16. /* 为了保证每一个链表元素的id不同,特意把id定义成一个全局静态变量 */  
  17. static int list_id = 0;  
  18.   
  19. /** 将指定元素插入到链表尾部 
  20.   *     head    : 表示要插入元素的链表的头部的地址 
  21.   * list    : 表示要插入到链表中的元素 
  22.   */  
  23. static void list_add(struct list **head, struct list *list)  
  24. {  
  25.     struct list *temp;  
  26.   
  27.     /* 判断链表是否为空 */  
  28.     if(NULL == *head)  
  29.     {  
  30.         /* 为空 */  
  31.         *head = list;  
  32.         (*head)->next = NULL;  
  33.     }  
  34.     else  
  35.     {  
  36.         /* 不为空 */  
  37.         temp = *head;  
  38.         while(temp)  
  39.         {  
  40.             if(NULL == temp->next)  
  41.             {  
  42.                 temp->next = list;  
  43.                 list->next = NULL;  
  44.             }  
  45.             temp = temp->next;  
  46.         }  
  47.     }  
  48. }  
  49.   
  50. /** 遍历一个链表,打印链表中每个元素所包含的数据 
  51.   * head : 表示要遍历的链表的头部的指针 
  52.   */  
  53. static void list_print(struct list **head)  
  54. {     
  55.     struct list *temp;  
  56.   
  57.     temp = *head;  
  58.   
  59.     printf(”list information :\n”);  
  60.     while(temp)  
  61.     {  
  62.         printf(”\tlist %d : %s\n”, temp->id, temp->data);  
  63.         temp = temp->next;  
  64.     }  
  65. }  
  66.   
  67. /** 将指定元素从链表尾部删除 
  68.   *     head    : 表示要删除元素的链表的头部的地址 
  69.   * id      : 表示要删除元素的标识 
  70.   * 返回值  : 0-成功,-1-失败 
  71.   */  
  72. static int list_del(struct list **head, int id)  
  73. {  
  74.     struct list *temp, *p;  
  75.     temp = *head;  
  76.   
  77.     if(NULL == temp)  
  78.     {  
  79.         /* 链表为空 */  
  80.         printf(”链表为空!\n”);  
  81.         return -1;  
  82.     }  
  83.     else  
  84.     {  
  85.         /* 判断匹配的元素是否为链表头部的元素 */  
  86.         if(id == temp->id)       /* 是链表头部 */  
  87.         {  
  88.             *head = temp->next;  
  89.             return 0;  
  90.         }  
  91.         else                    /* 不是链表头部 */  
  92.         {  
  93.             while(temp->next)  
  94.             {  
  95.                 p = temp;  
  96.                 temp = temp->next;  
  97.   
  98.                 if(id == temp->id)  
  99.                 {  
  100.                     p->next = temp->next;  
  101.                     return 0;  
  102.                 }  
  103.             }     
  104.             return -1;  
  105.         }  
  106.     }  
  107.   
  108.     return -1;  
  109. }  
  110.   
  111. /** 将指定id的元素所定义的内容进行修改 
  112.   *     head    : 表示要改变元素的链表的头部的地址 
  113.   * id      : 表示要改变元素的标识 
  114.   * content : 表示要改变的内容 
  115.   * 返回值  : 0-成功,-1-失败 
  116.   */  
  117. static int list_chg(struct list **head, int id, char *content)  
  118. {  
  119.     struct list *temp;  
  120.   
  121.     temp = *head;   /* 将链表的头部赋值给临时聊表变量 */  
  122.   
  123.     while(temp)     /* 对链表进行轮询 */  
  124.     {  
  125.         if(id == temp->id)  
  126.         {  
  127.             memset(temp->data, 0, sizeof(temp->data));  
  128.             sprintf(temp->data, ”%s”, content);  
  129.             temp->data[strlen(content)] = ’\0’;  
  130.             return 0;  
  131.         }  
  132.         temp = temp->next;  
  133.     }  
  134.     return -1;  
  135. }  
  136.   
  137. /** 将指定id的元素所定义的内容进行查找 
  138.   *     head    : 表示要查询元素的链表的头部的地址 
  139.   * id      : 表示要查询元素的标识 
  140.   * 返回值  : 0-成功,-1-失败 
  141.   */  
  142. static int list_query(struct list **head, int id)  
  143. {  
  144.     struct list *temp;  
  145.   
  146.     temp = *head;   /* 将链表的头部赋值给临时聊表变量 */  
  147.   
  148.     while(temp)     /* 对链表进行轮询 */  
  149.     {  
  150.         if(id == temp->id)  
  151.         {  
  152.             printf(”list %d : %s\n”, temp->id, temp->data);  
  153.             return 0;  
  154.         }  
  155.         temp = temp->next;  
  156.     }  
  157.   
  158.     /* 没有找到元素 */  
  159.     printf(”not finding!\n”);  
  160.       
  161.     return -1;  
  162. }  
  163.   
  164.   
  165. /* 主函数,程序的入口 */  
  166. int main(int argc, char *argv[])  
  167. {  
  168.     int i = 0;  
  169.     struct list *lists = NULL;  
  170.   
  171.     struct list temp_list;  
  172.   
  173.     /* 分配10个元素 */  
  174.     lists = malloc(sizeof(struct list) * 10);  
  175.     if(NULL == lists)  
  176.     {  
  177.         printf(”malloc error!\n”);  
  178.         return -1;  
  179.     }  
  180.   
  181.     /* 将分配的10个元素依次填充数据并加入到链表当中 */  
  182.     for(i = 0; i < 10; i++)  
  183.     {  
  184.         lists[i].id = list_id++;  
  185.         sprintf(lists[i].data, ”TECH-PRO - %d”, i);  
  186.   
  187.         list_add(&list_head, &lists[i]);  
  188.     }  
  189.   
  190.     /* 填充这个结构体并加入链表当中 */  
  191.     temp_list.id = list_id++;  
  192.     sprintf(temp_list.data, ”temp_list”);  
  193.     list_add(&list_head, &temp_list);  
  194.   
  195.     /* 删除链表中开始位置、中间位置、尾部的元素 */  
  196.     list_del(&list_head, 0);  
  197.     list_del(&list_head, 5);  
  198.     list_del(&list_head, 10);  
  199.   
  200.     /* 改变id为4的元素所对应的值为 “change!!!” */  
  201.     list_chg(&list_head, 4, ”change!!!”);  
  202.   
  203.     /* 查询链表中id为4的元素结点的内容 */  
  204.     list_query(&list_head, 4);  
  205.   
  206.     return 0;  
  207. }  
/* 包含的头文件 */




include <stdio.h>

include <stdlib.h>

include <string.h>

/* 定义一个表示链表的结构体指针 */
struct list {
int id; /* 标识这个元素方便查找 */
char data[20]; /* 链表中包含的元素 */
struct list next; / 指向下一个链表的指针 */
};

/* 定义一个链表头部 */
static struct list *list_head = NULL;

/* 为了保证每一个链表元素的id不同,特意把id定义成一个全局静态变量 */
static int list_id = 0;

/** 将指定元素插入到链表尾部
* head : 表示要插入元素的链表的头部的地址
* list : 表示要插入到链表中的元素
*/
static void list_add(struct list **head, struct list *list)
{
struct list *temp;

/* 判断链表是否为空 */
if(NULL == *head)
{
    /* 为空 */
    *head = list;
    (*head)-&gt;next = NULL;
}
else
{
    /* 不为空 */
    temp = *head;
    while(temp)
    {
        if(NULL == temp-&gt;next)
        {
            temp-&gt;next = list;
            list-&gt;next = NULL;
        }
        temp = temp-&gt;next;
    }
}

}

/** 遍历一个链表,打印链表中每个元素所包含的数据
* head : 表示要遍历的链表的头部的指针
*/
static void list_print(struct list **head)
{
struct list *temp;

temp = *head;

printf("list information :\n");
while(temp)
{
    printf("\tlist %d : %s\n", temp-&gt;id, temp-&gt;data);
    temp = temp-&gt;next;
}

}

/** 将指定元素从链表尾部删除
* head : 表示要删除元素的链表的头部的地址
* id : 表示要删除元素的标识
* 返回值 : 0-成功,-1-失败
*/
static int list_del(struct list **head, int id)
{
struct list *temp, *p;
temp = *head;

if(NULL == temp)
{
    /* 链表为空 */
    printf("链表为空!\n");
    return -1;
}
else
{
    /* 判断匹配的元素是否为链表头部的元素 */
    if(id == temp-&gt;id)       /* 是链表头部 */
    {
        *head = temp-&gt;next;
        return 0;
    }
    else                    /* 不是链表头部 */
    {
        while(temp-&gt;next)
        {
            p = temp;
            temp = temp-&gt;next;

            if(id == temp-&gt;id)
            {
                p-&gt;next = temp-&gt;next;
                return 0;
            }
        }   
        return -1;
    }
}

return -1;

}

/** 将指定id的元素所定义的内容进行修改
* head : 表示要改变元素的链表的头部的地址
* id : 表示要改变元素的标识
* content : 表示要改变的内容
* 返回值 : 0-成功,-1-失败
*/
static int list_chg(struct list **head, int id, char *content)
{
struct list *temp;

temp = *head;   /* 将链表的头部赋值给临时聊表变量 */

while(temp)     /* 对链表进行轮询 */
{
    if(id == temp-&gt;id)
    {
        memset(temp-&gt;data, 0, sizeof(temp-&gt;data));
        sprintf(temp-&gt;data, "%s", content);
        temp-&gt;data[strlen(content)] = '\0';
        return 0;
    }
    temp = temp-&gt;next;
}
return -1;

}

/** 将指定id的元素所定义的内容进行查找
* head : 表示要查询元素的链表的头部的地址
* id : 表示要查询元素的标识
* 返回值 : 0-成功,-1-失败
*/
static int list_query(struct list **head, int id)
{
struct list *temp;

temp = *head;   /* 将链表的头部赋值给临时聊表变量 */

while(temp)     /* 对链表进行轮询 */
{
    if(id == temp-&gt;id)
    {
        printf("list %d : %s\n", temp-&gt;id, temp-&gt;data);
        return 0;
    }
    temp = temp-&gt;next;
}

/* 没有找到元素 */
printf("not finding!\n");

return -1;

}

/* 主函数,程序的入口 */
int main(int argc, char *argv[])
{
int i = 0;
struct list *lists = NULL;

struct list temp_list;

/* 分配10个元素 */
lists = malloc(sizeof(struct list) * 10);
if(NULL == lists)
{
    printf("malloc error!\n");
    return -1;
}

/* 将分配的10个元素依次填充数据并加入到链表当中 */
for(i = 0; i &lt; 10; i++)
{
    lists[i].id = list_id++;
    sprintf(lists[i].data, "TECH-PRO - %d", i);

    list_add(&amp;list_head, &amp;lists[i]);
}

/* 填充这个结构体并加入链表当中 */
temp_list.id = list_id++;
sprintf(temp_list.data, "temp_list");
list_add(&amp;list_head, &amp;temp_list);

/* 删除链表中开始位置、中间位置、尾部的元素 */
list_del(&amp;list_head, 0);
list_del(&amp;list_head, 5);
list_del(&amp;list_head, 10);

/* 改变id为4的元素所对应的值为 "change!!!" */
list_chg(&amp;list_head, 4, "change!!!");

/* 查询链表中id为4的元素结点的内容 */
list_query(&amp;list_head, 4);

return 0;

}




本文的主要内容目录:

一、单向链表的C语言实现

二、单向链表的基本操作


一、单向链表的C语言实现

链表作为一种基本的数据结构在程序开发过程当中经常会使用到。对C语言来说链表的实现主要依靠结构体和指针,所以本文相关内容和程序需要有C语言当中指针和结构体的基础。

链表是一种线性存储数据的结构,存储内容在逻辑上连续的,在物理上却不一定连续。单向链表的组成包括一个链表头(head)和若干链表元素(node),对链表的基本操作其实就是增、删、改、查。

首先说说单向链表的C语言实现方法。为了实现一个单向链表,首先定义一个结构体:

  1. /* 定义一个表示链表的结构体指针 */  
  2. struct list {  
  3.     int id;         /* 标识这个元素方便查找 */  
  4.     char data[20];      /* 链表中包含的元素 */  
  5.     struct list *next;  /* 指向下一个链表的指针 */  
  6. };  
/* 定义一个表示链表的结构体指针 */
struct list {
    int id;         /* 标识这个元素方便查找 */
    char data[20];      /* 链表中包含的元素 */
    struct list *next;  /* 指向下一个链表的指针 */
};
下面来编写程序实现一个链表的基本操作。该程序的功能是首先分配若干个链表元素(node),然后对这些链表元素进行赋初值,赋完初值之后将这些链表元素依次加入到链表当中,最后把这些元素的data字段依次打印出来。(注意 :本程序实现的链表头结点(head)当中是存放数据的;为了保证每一个元素的id字段都不相同,所以定义了一个全局静态数据成员list_id;使用linux下的gcc进行编译)。程序如下:

  1. /* 包含的头文件 */  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4.   
  5. /* 定义一个表示链表的结构体指针 */  
  6. struct list {  
  7.     int id;         /* 标识这个元素方便查找 */  
  8.     char data[20];      /* 链表中包含的元素 */  
  9.     struct list *next;  /* 指向下一个链表的指针 */  
  10. };  
  11.   
  12. /* 定义一个链表头部 */  
  13. static struct list *list_head = NULL;  
  14.   
  15. /* 为了保证每一个链表元素的id不同,特意把id定义成一个全局静态变量 */  
  16. static int list_id = 0;  
  17.   
  18. /** 将指定元素插入到聊表尾部 
  19.   *     head    : 表示要插入元素的链表的头部的地址 
  20.   * list    : 表示要插入到链表中的元素 
  21.   */  
  22. static void list_add(struct list **head, struct list *list)  
  23. {  
  24.     struct list *temp;  
  25.   
  26.     /* 判断链表是否为空 */  
  27.     if(NULL == *head)  
  28.     {  
  29.         /* 为空 */  
  30.         *head = list;  
  31.         (*head)->next = NULL;  
  32.     }  
  33.     else  
  34.     {  
  35.         /* 不为空 */  
  36.         temp = *head;  
  37.         while(temp)  
  38.         {  
  39.             if(NULL == temp->next)  
  40.             {  
  41.                 temp->next = list;  
  42.                 list->next = NULL;  
  43.             }  
  44.             temp = temp->next;  
  45.         }  
  46.     }  
  47. }  
  48.   
  49. /** 遍历一个链表,打印链表中每个元素所包含的数据 
  50.   * head : 表示要遍历的链表的头部的指针 
  51.   */  
  52. static void list_print(struct list **head)  
  53. {     
  54.     struct list *temp;  
  55.   
  56.     temp = *head;  
  57.   
  58.     printf(”list information :\n”);  
  59.     while(temp)  
  60.     {  
  61.         printf(”\tlist %d : %s\n”, temp->id, temp->data);  
  62.         temp = temp->next;  
  63.     }  
  64. }  
  65.   
  66. /* 主函数,程序的入口 */  
  67. int main(int argc, char *argv[])  
  68. {  
  69.     int i = 0;  
  70.     struct list *lists = NULL;  
  71.   
  72.     /* 分配10个元素 */  
  73.     lists = malloc(sizeof(struct list) * 10);  
  74.     if(NULL == lists)  
  75.     {  
  76.         printf(”malloc error!\n”);  
  77.         return -1;  
  78.     }  
  79.   
  80.     /* 将分配的10个元素依次填充数据并加入到链表当中 */  
  81.     for(i = 0; i < 10; i++)  
  82.     {  
  83.         lists[i].id = list_id++;  
  84.         sprintf(lists[i].data, ”TECH-PRO - %d”, i);  
  85.   
  86.         list_add(&list_head, &lists[i]);  
  87.     }  
  88.   
  89.     /* 遍历链表,把链表中每个元素的信息都打印出来 */  
  90.     list_print(&list_head);  
  91.   
  92.     return 0;  
  93. }  
/* 包含的头文件 */




猜你喜欢

转载自blog.csdn.net/zhaozhiyuan111/article/details/79876216