关于链表的相关总结及代码参考

本文详细介绍了单向链表和双向链表的创建、遍历、查找、排序等基本操作,并提供了具体的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链表有一系列的节点组成(每个节点一般为结构体形式),节点在运行时动态生成(malloc)

    节点分为两部分:数据域、指针域

一、单向链表的创建、插入、遍历、查找、排序、逆序、删除、释放

    例:typedef struct student{
    
            int num;
            float score;
            struct student *next;
    
    }STU;
    1、链表的创建
        添加节点到链表到链表的尾部:1)当链表为空时,将链表的头直接指向待添加的新节点
        2)链表不为空时,首先遍历链表找到链表的尾节点,然后将待添加的新节点挂在尾节点上
        STU *head,*new;
        new=(STU *)malloc(sizeof(STU));
        void link_create(STU **head,STU *new)
        {
            //先定义一个中间变量,来保证头文件不变
            STU *p_mov=*head;
            if(*head==NULL)//插入第一个节点
            {
                *head=new;
                new->next=NULL;
            }
            else
            {
                while(p_mov->next!=NULL)//找到尾节点
                {
                    p_mov=p_mov->next;
                
                }
                p_mov->next=new;//将新节点添加到尾节点
                new->next=NULL;    
            }
        
        }
        添加节点到链表到链表的头部    
        void link_create(STU **head,STU *new)
        {
            if(*head==NULL)//插入第一个节点
            {
                *head=new;
                new->next=NULL;
            }
            else
            {
                new->next=*head;
                *head=new->next;
            }
        }
    2、链表的遍历    :遍历输出链表所有节点
        1)得到链表第一个节点的地址,即头结点  2)设一个临时指针变量p_mov,指向第一个节点head,即
        获得p_mov所指节点的信息  3)使p_mov指向下一个节点
        void link_print(STU *p_head)
        {
            STU *p_mov;
            p_mov=p_head;
            while(p_mov!=NULL)
            {
                printf("num=%d name= %s score=%d\n",p_mov->num,p_mov->name,p_mov->score);
                p_mov=p_mov->next;
            }
        
        
        }
    3、查找关键字:按照指定关键字查找所需节点
        1)得到链表的第一个节点的地址,即头结点  2)设一个临时指针变量p_mov,指向第一个节点head,即
        获得p_mov所指节点的信息  3)比较是否是要查找的节点
        
        STU *link_search_name(STU *head,char *name)
        {
            STU *p_mov;
            p_mov=p_head;
            while(p_mov!=NULL)
            {
                if(strcmp(p_mov->name,name)==0)
                {
                    return p_mov;
                
                }
                else  
                    p_mov=p_mov->next;
            }
            return NULL;
        
        }
    4、释放链表(从头节点一个一个的删除节点)
        1)释放节点前要先保存下一节点,即将下一节点的地址赋值给p_mov
        STU * link_free(STU **head)
        {
            STU *p_mov;
            p_mov=*head;
            while(*head!=NULL)
            {
            
                p_mov=*head;
                *head=*head->next;
                free(p_mov);
            }
            return NULL;
        }
        
    5、删除节点
    1)删除的是第一个节点,只需使head指向下一个节点
    2)删除的不是第一个节点,使被删除节点的前个节点指向后一个节点
        void link_delete_num(STU **p_head,int num)
        {
            //先定义2个指针,用来保存上一个节点和下一个节点,即该节点的上一节点的next指向该节点的
            下一节点
            STU *pb,pf;
            pb=pf=*p_head;
            if(*p_head==NULL)
            {
                printf("该链表为空,没有要删除的节点\n");
                return ;
            
            }
            while(pb->num!=num && pb->next!=NULL)
            {
                pf=pb;
                pb=pb->next;
            
            }
            if(pb->num==num)
            {
                if(pb==*p_head)
                {
                    *p_head=pb->next;
                }
                else
                {
                    pf->next=pb->next;
                }
                free(pb);
            }
            else
            {
                printf("没有您要删除的节点\n");
            }
            
        }
        
    6、插入节点
        1、链表为空时,插入节点即为头结点  2、查找3、找到(插在头或插在一般位置)或者找不到(查到最后)
        void link_insert_num(STU** head,STU* new)
        {
            STU *pb,*pf;
            pb=pf=*head;
            if(*head==NULL)
            {
                
                *head=new;
                new->next=NULL;
            }
            while((new->num<=pb->num)&&(pb->next)!=NULL)
            {
                pf=pb;
                pb=pb->next;
            
            }
            if(new->num >pb->num)
            {
                if(pb==*head)
                {
                    new->next=*head;
                   *head=new;
                }
                else
                {
                    pf->next=new;
                    new->next=pb;
                }
            }
            else
            {
                pb->next=new;
                new->next=NULL;
            
            }
        
        
        }
   7、排序
    void link_order_num(STU **head)
    {
        STU *pb,*pf,temp;
        pb=pf=head;
        if(head==NULL)
        {
            printf("链表为空\n");
            return 0;
        }
        while(pf->next!=NULL)
        {
            pb=pf->next;
                while(pb!=NULL)
                {
                    if(pb->num < pf->num)
                    {
                        temp=*pf;
                        *pf=*pb;
                        *pb=temp;
                        
                        temp->next=pf->next;
                        pf->next=pb->next;
                        pb->next=pf->next;
                        
                    }
                    pb=pb->next;
                }
            pf=pf->next;
        }
    
    }
    8、逆序
    STU *link_rever_num(STU *head)
    {
        STU *pb,*pf,*r;
        pb=pf=head;
        if(head==NULL)
        {
            printf("链表为空\n");
            return 0;
        }
        if(head->next==NULL)
        {
            printf("链表只有一个节点,不用逆序\n");
            return 0;
        }
        pb=pf->next;
        while(pb!=NULL)
        {
            r = pb->next;
            pb->next=pf;
            pf=pb;
            pb=r;
        
        }
        head->next=NULL;
        head=pf;
        return 0;
    }

二、双向链表

#include <stdio.h>
#include <stdlib.h>
typedef struct student
{ 					//数据域
	int num;		//学号
	int score;	//分数
	char name[20];
	struct student *front;
	struct student *next;//指针域
}STU;

/*****************双向链表的创建*****************************/
void double_link_creat_head(STU **p_head,STU *p_new)
{
	STU *p_mov=*p_head;
	if(*p_head==NULL)				//当第一次加入链表为空时,head执行p_new
	{
		*p_head=p_new;
		p_new->front=NULL;
		p_new->next=NULL;
	}
	else	//第二次及以后加入链表
	{		
		while(p_mov->next!=NULL)
		{
			p_mov=p_mov->next;	//找到原有链表的最后一个节点
		}	
		p_mov->next=p_new;		//将新申请的节点加入链表
		p_new->front=p_mov;
		p_new->next=NULL;
	}
}

/*****************双向链表的遍历******************************/
void double_link_print(STU *head)
{
	STU *pb;
	pb=head;
	if(head==NULL)
	{
		printf("链表为空\n");
		return ;
	}
	while(pb->next!=NULL)
	{
		printf("num=%d score=%d name:%s\n",pb->num,pb->score,pb->name);
		pb=pb->next;
	}
	printf("num=%d score=%d name:%s\n",pb->num,pb->score,pb->name);

	printf("\n\n\n\n");
	while(pb!=NULL)
	{
		printf("num=%d score=%d name:%s\n",pb->num,pb->score,pb->name);
		pb=pb->front;
	}


}

/**********************双向链表的插入******************************/
 void double_link_insert_num(STU **p_head,STU *p_new)
{
	STU *pb,*pf;
	pb=*p_head;
	if(*p_head == NULL)//链表为空,新来的节点就是头节点
	{
		*p_head=p_new;
		p_new->front=NULL;
		p_new->next=NULL;
		return ;
	}
	while((p_new->num >= pb->num) && (pb->next!=NULL) )
	{
		pb=pb->next ;
	}
	if(p_new->num < pb->num)//找到了一个pb的num比新来的节点的num大,插在pb前边
	{
		if(pb==*p_head)//找到的节点是头节点,插在头节点的前边
		{
			p_new->next=*p_head;
			(*p_head)->front=p_new;
			p_new->front=NULL;
			*p_head=p_new;
		}
		else
		{
			pf=pb->front;//pf指向 找到节点的前一个节点
			
			p_new->next=pb;
			p_new->front=pf;
			pf->next=p_new;
			pb->front=p_new;
		}
	}
	else//所有pb指向节点的num都比p_new指向的节点的num小,插在最后
	{
		pb->next=p_new;
		p_new->front=pb;
		p_new->next=NULL;
	}
}

int main()
{
	STU *head=NULL,*p_new=NULL;
	int num,i;
	printf("请输入链表初始个数:\n");
	scanf("%d",&num);
	for(i=0;i<num;i++)
	{	
		p_new=(STU*)malloc(sizeof(STU));//申请一个新节点
		printf("请输入学号、分数、名字:\n");	//给新节点赋值
		scanf("%d %d %s",&p_new->num,&p_new->score,p_new->name);
		double_link_creat_head(&head,p_new);	//将新节点加入链表
	}
	double_link_print(head);
	while(1)
	{
		p_new=(STU*)malloc(sizeof(STU));//申请一个新节点
		printf("请输入您要插入的节点的num score name\n");
		scanf("%d %d %s",&p_new->num,&p_new->score,p_new->name);
		double_link_insert_num(&head,p_new);
		double_link_print(head);
		
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值