c语言链表移动北理工,C语言---链表(包括学习过程中的思想活动)

本文通过一个简单的链表实现例子,详细解释了链表的数据结构和工作原理,包括如何创建、打印和释放链表。在创建链表的过程中,涉及到了结构体定义、动态内存分配以及用户输入处理。同时,文章还讨论了在处理数字存储时遇到的问题,并给出了打印链表和释放链表内存的方法。通过对链表的实践操作,加深了对这一基础数据结构的理解。
摘要由CSDN通过智能技术生成

写链表想法的由来:

链表---重要的数据结构,工作了这么长时间,再也没有写过链表,可能是由于工作中没有使用的原因,也可能是我太懒了,还可能是因为玩游戏玩过头了吧!总之我知道有链表,但是链表是什么好想就天马行空了,所以决定写一下,哈哈,虽然我很菜,但是再菜我也要它跑起来,万一哪天要用那么一下子呢!好了废话不多说,来满足一下自己的小小的一个期望(它跑起来)。

特简单的:

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

#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掉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值