写链表想法的由来:
链表---重要的数据结构,工作了这么长时间,再也没有写过链表,可能是由于工作中没有使用的原因,也可能是我太懒了,还可能是因为玩游戏玩过头了吧!总之我知道有链表,但是链表是什么好想就天马行空了,所以决定写一下,哈哈,虽然我很菜,但是再菜我也要它跑起来,万一哪天要用那么一下子呢!好了废话不多说,来满足一下自己的小小的一个期望(它跑起来)。
特简单的:
首先呢!先码一个特别简单的,主要是为了先了解一下嘛!然后在一点点深入嘛!毕竟这么长时间没有写过了,不是嘛?
#include #include
structnode {intnumber;struct node *next;
};
typedefstructnode 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("");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
2 #include
3 #include
4
5 structnode {6 char name[16];7 char number[16];8 //long long number;
9 struct node *next;10 };11
12 typedef structnode Node;13
14 Node *createList(intnum)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!");26 gotoerr;27 }28
29 head->next =NULL;30
31 tmp =head;32
33 for(i = 1; i <= num; i++) {34 printf("create [%d] node!", i);35 node = (Node *)malloc(sizeof(Node));36 if (!node) {37 printf("malloc Node(node) error!");38 }39
40 printf("Please enter your name :");41 scanf("%s", &node->name);42 if (!node->name) {43 printf("enter the name error! Please enter again!");44 gotoerr;45 }46
47 printf("Please enter yout number :");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!");52 gotoerr;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!
");63 //goto err;64 //}
65
66 tmp->next =node;67 tmp =node;68 }69 node->next =NULL;70 returnhead;71
72 err:73 returnNULL;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", 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!", i);98 tmp = tmp->next;99 i++;100 }101 tmp =NULL;102
103 free(node);104 node =NULL;105
106 printf("clear finish!");107 }108
109 int main(void)110 {111 Node *node =NULL;112 intnum;113
114 printf("Please enter the number of nodes int the link_list :");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", 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掉。