C语言终极之链表
链表与数组的区别
数组:顺序存储,大小固定
链表:随机储存,可存放不同类型的结构体数据
数组的特性
#include <stdio.h>
int main()
{
int array[]={1,2,3,4};
int i;
for(i=0;i<sizeof(array)/sizeof(array[0]);i++){
printf("%d ",array[i]);
}
putchar('\n');
return 0;
}
静态链表
程序A:访问方式(每次以起始节点向后访问)
#include <stdio.h>
struct test
{
int data;
struct test *next;
};
int main()
{
struct test t1 = {1,NULL};
struct test t2 = {2,NULL};
struct test t3 = {3,NULL};
t1.next = &t2; /
t2.next = &t3;
printf("%d %d %d \n",t1.data,t1.next->data,t1.next->next->data);
//第二个数:进入结构体指针所以要用 “->” ,再指向 data
return 0;
}
程序B:通过节点地址手动相连关系访问
#include <stdio.h>
struct test
{
int data;
struct test *next;
};
void printlink(struct test *head)
{
struct test *point =head;
while(1){
if(point != NULL){ //不是空指针,输出数值,并地址向后偏移
printf("%d ",point->data);
point = point->next;
}else{ //指针为空,则跳出程序
puchar('\n');
break;
}
}
}
int main()
{
struct test t1 = {1,NULL};
struct test t2 = {2,NULL};
struct test t3 = {3,NULL};
t1.next = &t2;
t2.next = &t3;
printlink(&t1); //通过传递链表首元素的地址
return 0;
}
静态链表 计算节点个数
#include <stdio.h>
struct test
{
int data;
struct test *next;
};
void printlink(struct test *head)
{
struct test *point =head;
while(1){
if(point != NULL){ //不是空指针,打印数值,并指针向后偏移
printf("%d ",point->data);
point = point->next;
}else{ //指针为空,则跳出程序
putchar('\n');
break;
}
}
}
int node_Number(struct test *head)
{
int num = 0;
struct test *point = head;
while(point != NULL){
++num; //指针每进入循环一次,+1
point = point -> next;
}
return num; //返回节点个数
}
int main()
{
struct test t1 = {1,NULL};
struct test t2 = {2,NULL};
struct test t3 = {3,NULL};
t1.next = &t2;
t2.next = &t3;
printlink(&t1); //通过传递首元素的地址(打印链表)
int ret = node_Number(&t1); //计算链表个数
printf("链表的节点个数是%d\n",ret);
return 0;
}
静态链表 查找节点
#include <stdio.h>
struct test
{
int data;
struct test *next;
};
void printlink(struct test *head)
{
struct test *point =head;
while(1){
if(point != NULL){ //不是空指针,打印数值,并指针向后偏移
printf("%d ",point->data);
point = point->next;
}else{
putchar('\n');
break;
}
}
}
int seek_node(struct test *head,int data)
{
struct test *point = head;
while(point != NULL){
if(point -> data == data){ //链表节点的数值 等于 查找的数值 进行对比
return 1;
}
point = point -> next;
}
return 0;
}
int main()
{
struct test t1 = {1,NULL};
struct test t2 = {2,NULL};
struct test t3 = {3,NULL};
t1.next = &t2;
t2.next = &t3;
printlink(&t1); //通过传递首元素的地址(打印链表)
int ret = seek_node(&t1,2); //获取seek_node函数的返回值
if(ret == 1){
printf("链表中有 1\n");
}else{
printf("链表中没 1\n");
}
ret = seek_node(&t1,8);
if(ret == 1){
printf("链表中有 8\n");
}else{
printf("链表中没 8 \n");
}
return 0;
}
静态链表从指定节点后方插入新节点
**思路
a.找到指定的节点
b.新节点地址 指向 指定节点的下一个节点地址
c.指定节点的下一个节点地址 指向 新节点 **
#include <stdio.h>
struct test
{
int data;
struct test *next;
};
void printlink(struct test *head)
{
struct test *point =head;
while(1){
if(point != NULL){ //不是空指针,打印数值,并指针向后偏移
printf("%d ",point->data);
point = point->next;
}else{ //指针为空,则跳出程序
putchar('\n');
break;
}
}
}
int Insert_after_node(struct test *head,struct test *new,int data)
{
struct test *point = head;
while(point != NULL){
if(point -> data == data){ // a.找到指定的节点
new ->next = point -> next; // b.新节点地址 指向 指定节点的下一个节点地址
point ->next = new; // c.指定节点的下一个节点地址 指向 新节点
return 1;
}
point = point ->next;
}
return 0;
}
int main()
{
struct test t1 = {1,NULL};
struct test t2 = {2,NULL};
struct test t3 = {3,NULL};
struct test t4 = {4,NULL};
struct test t5 = {5,NULL};
t1.next = &t2;
t2.next = &t3;
t3.next = &t4;
t4.next = &t5;
struct test new = {100,NULL};
printlink(&t1); //通过传递首元素的地址
int ret = Insert_after_node(&t1,&new,3);
if(ret == 1){ //判断是否插入成功
printf("插入成功\n");
}else{
printf("插入失败\n");
}
printlink(&t1); //通过传递首元素的地址
return 0;
}
静态链表从指定节点前方插入新节点
思路
A. 头节点插入
B.中间以及尾部插入
#include <stdio.h>
struct test
{
int data;
struct test *next;
};
void printlink(struct test *head)
{
struct test *point =head;
while(1){
if(point != NULL){ //不是空指针,打印数值,并指针向后偏移
printf("%d ",point->data);
point = point->next;
}else{ //指针为空,则跳出程序
putchar('\n');
break;
}
}
}
struct test *Insert_front_node(struct test *head,struct test *new,int data)
{
struct test *point = head;
if(point -> data == data){ //A. 头节点插入
new -> next = point;
return new; //切记:返回的是新节点头
}
while(point -> next != NULL){ //B.中间以及尾部插入
if(point -> next -> data == data){
new ->next = point -> next;
point ->next = new;
return head; //切记:需要返回值原节点
}
point = point ->next;
}
return head;
}
int main()
{
struct test t1 = {1,NULL};
struct test t2 = {2,NULL};
struct test t3 = {3,NULL};
struct test t4 = {4,NULL};
struct test t5 = {5,NULL};
t1.next = &t2;
t2.next = &t3;
t3.next = &t4;
t4.next = &t5;
struct test new = {100,NULL};
struct test *head = &t1;
printlink(head); //通过传递首元素的地址
head= Insert_front_node(head,&new,1); //图一的效果
printlink(head); //通过传递首元素的地址
//head= Insert_front_node(head,&new,3); //图二的效果
//printlink(head);
return 0;
}
图一:
图二:
静态链表删除指定节点
#include <stdio.h>
struct test
{
int data;
struct test *next;
};
void printlink(struct test *head)
{
struct test *point =head;
while(1){
if(point != NULL){ //不是空指针,打印数值,并指针向后偏移
printf("%d ",point->data);
point = point->next;
}else{ //指针为空,则跳出程序
putchar('\n');
break;
}
}
}
struct test *delete_node(struct test *head,int data)
{
struct test *point = head;
if(head -> data == data){
head = head -> next;
return head;
}
while(point -> next != NULL){
if(point -> next -> data == data){
point -> next = point -> next -> next;
return head;
}
point = point ->next;
}
}
int main()
{
struct test t1 = {1,NULL};
struct test t2 = {2,NULL};
struct test t3 = {3,NULL};
struct test t4 = {4,NULL};
struct test t5 = {5,NULL};
t1.next = &t2;
t2.next = &t3;
t3.next = &t4;
t4.next = &t5;
struct test new = {100,NULL};
struct test *head = &t1;
printf("原链表的节点:");
printlink(head); //通过传递首元素的地址
head = delete_node(head,1); //任意修改链表节点
printf("删除后的链表:");
printlink(head); //通过传递首元素的地址
return 0;
}
动态链表之头插法(程序A与程序B结果相同,但程序B使用函数分装)
程序A
#include <stdlib.h>
#include <stdio.h>
struct test
{
int data;
struct test *next;
};
void printlink(struct test *head)
{
struct test *point =head;
while(1){
if(point != NULL){ //不是空指针,打印数值,并指针向后偏移
printf("%d ",point->data);
point = point->next;
}else{ //指针为空,则跳出程序
putchar('\n');
break;
}
}
}
struct test *head_insert(struct test *head)
{
struct test *new;
while(1){
new = (struct test *)malloc(sizeof(struct test));
printf("请输入新节点:");
scanf("%d",&(new->data));
if(new->data ==0){
printf("输入0,即将退出程序\n");
return head;
}
if(head == NULL){ //刚创建链表时,链表为空
head = new; //所以将第一个数表示为链表头
}else{ //当链表中有数时
new -> next= head; //新节点的地址 指向 节点头
head = new; //新节点为链表头
}
}
return head;
}
int main()
{
struct test *head = NULL;
head = head_insert(head);
printlink(head); //通过传递首元素的地址
}
程序B
#include <stdlib.h>
#include <stdio.h>
struct test
{
int data;
struct test *next;
};
void printlink(struct test *head)
{
struct test *point =head;
while(1){
if(point != NULL){ //不是空指针,打印数值,并指针向后偏移
printf("%d ",point->data);
point = point->next;
}else{ //指针为空,则跳出程序
putchar('\n');
break;
}
}
}
struct test *head_insert(struct test *head,struct test *new) //头插法
{
if(head == NULL){
head = new;
}else{
new -> next= head;
head = new;
}
return head;
}
struct test *link_create(struct test *head) //创建链表
{
struct test *new;
while(1){
new = (struct test *)malloc(sizeof(struct test));
printf("请输入新节点:");
scanf("%d",&(new->data));
if(new->data ==0){
free(new);
printf("输入0,即将退出程序\n");
return head;
}
head = head_insert(head,new);
}
}
int main()
{
struct test *head = NULL;
head = link_create(head);
printlink(head); //通过传递首元素的地址
}
动态链表之尾插法
include <stdlib.h>
#include <stdio.h>
struct test
{
int data;
struct test *next;
};
void printlink(struct test *head)
{
struct test *point =head;
while(1){
if(point != NULL){ //不是空指针,打印数值,并指针向后偏移
printf("%d ",point->data);
point = point->next;
}else{ //指针为空,则跳出程序
putchar('\n');
break;
}
}
}
struct test *tail_insert(struct test *head,struct test *new) //尾插链表
{
struct test *point =head;
if(head == NULL){ //判断链表是否为空
head = new; //若为空,则将新节点 为 链表头
return head;
}
while(point -> next != NULL){ //判断链表的下一个是否为空
point = point -> next; //若不为空,直至走到链表节点的尾巴
} //退出循环
point -> next = new; //将新节点存储到链表尾巴
return head;
}
struct test *link_create(struct test *head)
{
struct test *new;
while(1){
new = (struct test *)malloc(sizeof(struct test));
printf("请输入新节点:");
scanf("%d",&(new->data));
if(new->data ==0){
free(new);
printf("输入0,即将退出程序\n");
return head;
}
head = tail_insert(head,new);
}
}
int main()
{
struct test *head = NULL;
head = link_create(head);
printlink(head); //通过传递首元素的地址
}