一个最简单的链表
大家一般看到的链表都是在直接使用堆 malloc分配空间然后封装成函数 个人觉得不是很适合初学者 或者说 太突兀了 和之前的内容 间隔过多了 甚至于我每次想要复习链表都要很大的勇气来 翻看那很长一串的代码 很抽象的代码 但是这个是我想出来的最简单的一个链表 这个只能有我们自己使用 长度里面的值都是写死了的 但是 很简洁 没有封装 和一些其他的东西
#include "head.h"
typedef struct node
{
int value;
// node_t * next;
struct node *next;
} node_t;
int main()
{
node_t head;
node_t *temp = head.next;
head.value = -1;
// NULL 一般作为一个宏出现 是被封装在 stddef里面的
head.next = NULL;
node_t n1 = {.next = NULL, .value = 1};
node_t n2 = {.next = NULL, .value = 2};
node_t n3 = {.next = NULL, .value = 3};
node_t n4 = {.next = NULL, .value = 4};
node_t n5 = {.next = NULL, .value = 5};
head.next = &n1;
n1.next = &n2;
n2.next = &n3;
n3.next = &n4;
n4.next = &n5;
temp = &head;
for (int i = 0; i < 20; i++)
{
printf("%d ", temp->value);
temp = temp->next;
if (temp->next == NULL)
{
break;
}
}
return 0;
}
一些问题
为什么不用for循环
for (int i = 0; i < 10; i++)
{
node_t new_node = {.next = NULL, .value = i};
printf("new_node %p \n", &new_node);
printf("head %p \n", &head);
node_t *temp = head.next;
printf("temp %p \n", temp);
// temp.next = new_node;
head.next = &new_node;
new_node.next = temp;
/* code */
}
这个是一个for循环的 链表 但是这个我测试了几次都是 报错 出来的内容很抽象 然后我就看了一下 就是 c语言在一个作用域里面 生成的变量分配的 地址是相同的 即 我每次 生成 new_node 都是相同的地址 根本无法生成 链表
同样也就无法使用 函数封装了 函数里面也是 创建的都是相同的 但是虽然这个有这么多的弊端 还是感觉这个很适合初学者 或者说 拾起来这部分内容的
2 malloc和正常方式
好了,我们现在对比 一下malloc 和正常的方式 分配的内存有什么区别
for (size_t i = 0; i < 10; i++)
{
// 1-使用正常的方式 在栈中开辟空间
node_t new_1;
node_t *new = &new_1;
// 2-使用malloc创建
// node_t *new = (node_t *)malloc(sizeof(node_t));
new->value = 10;
new->next = NULL;
printf(" new %p\n", new);
}
1输出
可以看到 第一种栈上的方式分配出来的每个地址都是相同的 那么 这个肯定是我发创建链表的 或者说 封装成一种 函数 在一定的作用域里面 将这部分抽象出来的
new 0x7fffffffdec0
new 0x7fffffffdec0
new 0x7fffffffdec0
new 0x7fffffffdec0
new 0x7fffffffdec0
new 0x7fffffffdec0
new 0x7fffffffdec0
new 0x7fffffffdec0
new 0x7fffffffdec0
new 0x7fffffffdec0
2-输出
可以看到malloc 开辟出来的每个地址空间都是不同的 这个就可以满足需求了 将这部分封装起来
new 0x555555756260
new 0x555555756690
new 0x5555557566b0
new 0x5555557566d0
new 0x5555557566f0
new 0x555555756710
new 0x555555756730
new 0x555555756750
new 0x555555756770
new 0x555555756790
3 malloc main创建链表
1-正常使用malloc创建链表
这种方式是可以使用重复的变量名字创建链表的 即 可以使用 for循环添加数据
#include "head.h"
typedef struct node
{
int value;
struct node *next;
} node_t;
int main()
{
node_t head;
node_t *temp;
head.value = -1;
// NULL 一般作为一个宏出现 是被封装在 stddef里面的
head.next = NULL;
for (size_t i = 0; i < 10; i++)
{
// 1-使用正常的方式 在栈中开辟空间
// node_t new_1;
// node_t *new = &new_1;
// 2-使用malloc创建
node_t *new = (node_t *)malloc(sizeof(node_t));
new->value = i;
new->next=head.next;
head.next=new;
printf(" new %p\n", new);
}
temp = &head;
for (int i = 0; i < 20; i++)
{
printf("%d ", temp->value);
temp = temp->next;
if (temp->next == NULL)
{
break;
}
}
return 0;
}
结果正常
new 0x555555756260
new 0x555555756690
new 0x5555557566b0
new 0x5555557566d0
new 0x5555557566f0
new 0x555555756710
new 0x555555756730
new 0x555555756750
new 0x555555756770
new 0x555555756790
-1 9 8 7 6 5 4 3 2 1 [1]
2-测试 栈上开辟空间
这种方式无法正常创建链表
#include "head.h"
typedef struct node
{
int value;
struct node *next;
} node_t;
int main()
{
node_t head;
node_t *temp;
head.value = -1;
// NULL 一般作为一个宏出现 是被封装在 stddef里面的
head.next = NULL;
for (size_t i = 0; i < 10; i++)
{
// 1-使用正常的方式 在栈中开辟空间
node_t new_1;
node_t *new = &new_1;
// 2-使用malloc创建
//node_t *new = (node_t *)malloc(sizeof(node_t));
new->value = i;
new->next=head.next;
head.next=new;
printf(" new %p\n", new);
}
temp = &head;
for (int i = 0; i < 20; i++)
{
printf("%d ", temp->value);
temp = temp->next;
if (temp->next == NULL)
{
break;
}
}
return 0;
}
结果错误
new 0x7fffffffdec0
new 0x7fffffffdec0
new 0x7fffffffdec0
new 0x7fffffffdec0
new 0x7fffffffdec0
new 0x7fffffffdec0
new 0x7fffffffdec0
new 0x7fffffffdec0
new 0x7fffffffdec0
new 0x7fffffffdec0
-1 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
3-malloc数组类型转链表
#include "head.h"
typedef struct node
{
int value;
struct node *next;
} node_t;
int main()
{
node_t head;
node_t *temp;
head.value = -1;
// NULL 一般作为一个宏出现 是被封装在 stddef里面的
head.next = NULL;
int arr[10] = {5, 2, 0, 1, 3, 1, 4};
for (size_t i = 0; i < 10; i++)
{
node_t *new = (node_t *)malloc(sizeof(node_t));
new->value = arr[i];
new->next = head.next;
head.next = new;
printf(" new %p\n", new);
}
temp = &head;
for (int i = 0; i < 20; i++)
{
temp = temp->next;
printf("%d ", temp->value);
if (temp->next == NULL)
{
break;
}
}
return 0;
}