7.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);                //通过传递首元素的地址
}

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值