C语言---链表(包括学习过程中的思想活动)

写链表想法的由来:

  链表---重要的数据结构。

特简单的:

  首先呢!先码一个特别简单的,主要是为了先了解一下嘛!然后在一点点深入嘛!毕竟这么长时间没有写过了,不是嘛?

#include <stdio.h>
#include <stdlib.h>

struct node {
    int number;
    struct node *next;
};

typedef struct node Node;

int main(void)
{
    Node *head, *b, *c; 

    head = (Node *)malloc(sizeof(Node));   
    b = (Node *)malloc(sizeof(Node));   
    c = (Node *)malloc(sizeof(Node));   

    b->number = 20; 
    c->number = 30; 

    head->next = b;
    b->next = c;

    while (head) {
        printf("---->%d", head->number);

        head = head->next;
    }   
    printf("\n");

    free(head);
    free(b);
    free(c);

    return 0;
}
// 执行结果

  [root@yuan misc]# gcc link_list.c
  [root@yuan misc]# ./a.out
  ---->0---->20---->30

  链表从表面的意思上就是链状的表,就像一根线上系了很多一样的结,这些结就是我们定义的结构体,而链就是我们定义的结构体中的指针next。next中存放着下一个节点的地址,这样我们就把所有的节点串联了起来,就像我们上边执行的结果一样。其实就是指针将数据串联。

稍微有点复杂的:

  (我觉得上边码的那个并不算是真正意义上的链表,我们只是把三个结构体变量串联了起来)写一个稍微复杂点的链表:  

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 struct node {
  6     char name[16];
  7     char number[16];
  8     // long long number;
  9     struct node *next;
 10 };
 11 
 12 typedef struct node Node;
 13 
 14 Node *createList(int num)
 15 {
 16     Node *head = NULL;
 17     Node *tmp = NULL;
 18     Node *node = NULL;
 19     int i = 0;
 20     // int count = 0;
 21     // long long tmpNum;
 22 
 23     head = (Node *)malloc(sizeof(Node));
 24     if (!head) {
 25         printf("malloc Node(head) error!\n");
 26         goto err;
 27     }   
 28 
 29     head->next = NULL;
 30 
 31     tmp = head;
 32 
 33     for(i = 1; i <= num; i++) {
 34         printf("create [%d] node!\n", i); 
 35         node = (Node *)malloc(sizeof(Node));
 36         if (!node) {
 37             printf("malloc Node(node) error!\n");
 38         }   
 39     
 40         printf("Please enter your name :\n");
 41         scanf("%s", &node->name);
 42         if (!node->name) {
 43             printf("enter the name error! Please enter again!\n");
 44             goto err;
 45         }   
 46 
 47         printf("Please enter yout number :\n");
 48         // scanf("%d", &node->number);
 49         scanf("%s", &node->number);
 50         if (strlen(node->number) != 11) {
 51             printf("enter the number error! Please enter again!\n");
 52             goto err;
 53         }   
 54 
 55         // tmpNum = node->number;
 56         // while(tmpNum) {
 57         //  tmpNum /= 10;
 58         //  count++;
 59         // }
 60 
 61         // if (count != 10) {
 62         //  printf("enter the number error! Please enter again!\n");
 63         //  goto err;
 64         // }
 65 
 66         tmp->next = node;
 67         tmp = node;
 68     }   
 69     node->next = NULL;
 70     return head;
 71 
 72 err:
 73     return NULL;
 74 }
 75 
 76 void printList(Node *node)
 77 {
 78     Node *tmp = NULL;
 79 
 80     tmp = node->next;
 81 
 82     while(tmp) {
 83         printf("name : %s, number : %s\n", tmp->name, tmp->number);
 84         tmp = tmp->next;
 85     }   
 86 }
 87 
 88 void freeList(Node *node)
 89 {
 90     Node *tmp = NULL;
 91     int i = 1;
 92 
 93     tmp  = node->next;
 94 
 95     while(tmp) {
 96         free(tmp);
 97         printf("clean up [%d] node!\n", i); 
 98         tmp = tmp->next;
 99         i++;
100     }   
101     tmp = NULL;
102 
103     free(node);
104     node = NULL;
105 
106     printf("clear finish!\n");
107 }
108 
109 int main(void)
110 {
111     Node *node = NULL;
112     int num;
113 
114     printf("Please enter the number of nodes int the link_list :\n");
115     scanf("%d", &num);
116     node = createList(num);
117     printList(node);
118     freeList(node);
119 
120     return 0;
121 }
// 执行结果

[root@localhost address_list]# ./a.out 
Please enter the number of nodes int the link_list :
2
create [1] node!
Please enter your name :
test
Please enter your number :
12345678901
create [2] node!
Please enter your name :
test2
Please enter your number :
12345678902
name : test, number : 12345678901
name : test2, number : 12345678902
clean up [1] node!
clean up [2] node!
clear finish!

  代码中有部分注掉的,那部分是因为数字长度的问题,我试了%ll,%l64d, %lld,%ld输出的结果都不是期望值,所以就改用了字符串,这个问题有时间我在查一下吧!

  逐句分析:

    首先我们定义了一个结构体Node,结构体成员有三个,用来存储一个人名和其对应的电话号码(11位),next指针用来指向下一个节点;

    在main函数中,先要输入一个数字,来确定我们的链表的长度,然后创建链表,将其存储的内容打印出来,最后释放各个节点。

      createList函数中:

      生成一个头节点,根据num确定需要生成节点的个数,并对其各个节点进行赋值。

      createList函数中我们定义了三个结构体变量,一个是头节点head,一个是节点node,还有一个临时结构体变量tmp。我们将头节点head赋值给中间变量tmp,然后分配一个新的节点node,将node赋值给中间变量tmp结构体成员变量中的next指针变量(也就是头节点head结构体成员变量中的next指针变量),这样头节点就和新分配的节点node串联起来了。其中有一句tmp = node,这句话表示将新生成的节点node赋值给了中间变量tmp,这样做是为了在下一次循环中中间变量tmp表示的是上一次分配的node节点,再次分配新的节点后和现在的中间变量tmp(也就是上一次分配的节点)串联。描述的有点乱,仔细想一下也不是那么乱。

      当循环结束后,将最后分配的节点node结构体成员中的next指针变量指向NULL。

      返回头节点head。

    printList函数中:

      刚开始是这样写的:

void printList(Node *node)
{
    while(node) {
        printf("name : %s, number : %s\n", node->name, node->number);
        node = node->next;
    }   
}
// 执行结果

[root@localhost address_list]# ./a.out
Please enter the number of nodes int the link_list :
2
create [1] node!
Please enter your name :
test
Please enter your number :
12345678901
create [2] node!
Please enter your name :
test2
Please enter your number :
12345678902
name : , number :
name : test, number : 12345678901
name : test2, number : 12345678902
clean up [1] node!
clean up [2] node!
clear finish!

    从执行结果中可以看出,我们链表长度是2,但是在打印的出来的结果中去出现三个,只是因为其中空的那个是头节点。

  freeList函数:

    由于使用了malloc函数动态分配就需要free函数掉,防止内存泄漏,其中有一句tmp  = NULL;这句是为了防止野指针,但是NULL也是一个地址,只不过这个地址是确定的(void *)0;但是这句话加到循环里就会出现问题,因为在free掉tmp后这个指针还是存在的,可能就是野指针吧(这里我不确定),但是这时的tmp确确实实是存在的,所以才有了下面的操作。而当我们将tmp制空后,它的地址也就不存在了,我们在进行后边的操作的时候就操作非法地址,就会出现段错误。

    还需将头节点free掉。

posted @ 2020-04-13 16:33  insistYuan  阅读(373)  评论(0编辑  收藏  举报