注意,请认真学习完《C程序设计(第五版)》第九章后再阅读本文会有更大的收获。
链表
概念理解
链表,用一条链来连接各个节点的数据。每个节点都会存储指向下一个节点的指针,最后一个节点指向一个空指针。
链表节点,通常节点会存储多种数据类型,一般采用结构体来定义。
链表与数组
如果把数组当作一种特殊的链表,虽然每个节点没有存储的指向下一个节点的指针,但是因为数组的独特性,我们可以根据数组类型来把当前节点指针做加法运算(元素数据类型所占内存的长度)就能得到下个节点的指针了。
链表存在的意义
数组在定义时需要指定长度,想要保证够用就需要把长度设置的足够长,这样会浪费存储空间,动态的根据需要进行扩展就是链表存在的意义。
链表操作
通过代码来练习链表的操作,链表一般结合动态内存分配进行运用,使用到之前学习的malloc()函数。
先定义一个结构体作为链表的节点,结构体里的*next成员指向同一个结构体。
typedef struct People{
int index;
char name[30];
struct People *next;
} PEOPLE;
注意:这里使用typedef来给结构体重新命名,在使用的时候能够更加便捷。
初始化一个链表
用malloc()函数的好处在这里体现了,我们可以定义任意多个节点并且都使用指针来进行引用与赋值操作,无需为每个节点都定义一个变量名。
/*
* 初始化一个链表
* @param int link_list_length 链表长度
*/
static PEOPLE *initLinkList(int link_list_length) {
PEOPLE *p, *previous, *start;
int length = sizeof(PEOPLE);
start = malloc(length);
if (!start){
return NULL;
}
start->index = 0;
start->next = NULL;
previous = start;
for (int i = 1; i < link_list_length; i++){
p = malloc(length);
if (p){
p->index = i;
p->next = NULL;
previous->next = p;
}
previous = p;
}
return start;
}
初始化之后的链表,我们通常使用首个节点的指针进行引用。
输出链表
使用while循环来输出链表节点中的数据,终止条件就是最后一个节点指向下一个节点的指针为NULL。
/*
* 输出链表
*/
static void printfLinkList(struct People *start) {
printf("========BEGIN========\n");
while (start != NULL){
printf("struct index is: %d\n", start->index);
start = start->next;
}
printf("========END========\n");
}
插入一个节点
插入到第N个节点的位置,那么原有的节点指向逻辑发生变化:原来的N-1节点指向新插入的N,新插入的N指向原来的N,也就是把原来的位置N变成了N+1。
/*
* 向链表中某个位置插入值
* @param PEOPLE start 链表起始节点指针
* @param PEOPLE insert 要插入的数据指针
* @param int position 插入的位置
*/
static PEOPLE *insertIntoLinkList(PEOPLE *start, PEOPLE *insert, int position) {
PEOPLE *origin, *next;
origin = start;
if (start == NULL || position == 0){
insert->next = start;
origin = insert;
} else{
int i = 1;
while (start != NULL){
next = start->next;
if (i == position){
start->next = insert;
insert->next = next;
}
i++;
start = next;
}
}
return origin;
}
删除某个节点
可以根据节点里的成员值删除,也可以像插入一样根据位置删除,这里代码示例根据节点里的成员值删除。
删除节点N也就意味着把原来的N-1节点从指向N节点变成指向N+1节点。
/*
* 删除链表中某个节点
* @param PEOPLE start 链表起始节点指针
* @param int index 删除的节点的成员index值
*/
static PEOPLE *removeFromLinkList(PEOPLE *start, int index) {
PEOPLE *origin, *previous, *next;
origin = start;
previous = NULL;
while (start != NULL){
next = start->next;
if (index == 0){
origin = next;
printf("remove index is: %d\n", start->index);
break;
}
if (index == start->index && previous){
previous->next = next;
printf("remove index is: %d\n", start->index);
break;
}
previous = start;
start = next;
}
return origin;
}