【C语言】单链表(二)

前言

前面我们已经实现了链表的创建、插入(头插法)、删除、打印功能,下面我们来实现,查找和指定位置插入

5、指定位置插入

5.1前驱插入

//指定位置的前面插入,和按值删除类似
void Inster_PostionPrecursor_List(Lnode* Head_Node,Node_Data posdata,Node_Data data)
{
    Lnode* posNode = Head_Node->next;
    Lnode* posNodeFront = Head_Node;
    Lnode* New_Node = Create_New_Node(data);
    if(posNode == NULL || New_Node == NULL)
    {
        printf("插入失败,此链表为空\n");
        return ;
    }
    else
    {
        while(posNode->data != posdata)
        {
            posNodeFront = posNode;
            posNode = posNode->next;
            if(posNode == NULL)
            {
                printf("插入失败\n");
                return ;
            }
        }
        New_Node->next = posNode;
        posNodeFront->next = New_Node;
       // printf("插入成功\n");
    }
}

posNode为指定的位置节点,posNodeFront为指定位置节点的前驱,New_Node为待插入节点。
while(posNode->data != posdata)遍历链表,直到找到posdata所在的节点,确保遍历过程中posNodeposNodeFront一前一后( posNodeFront = posNode; posNode = posNode->next;),当不满足循环条件时,表示此时posNode节点是我们想找到的节点,接下来插入节点New_Node

在这里插入图片描述

谨记插入过程中,一和二的顺序别写反了
①、New_Node->next = posNode;
②、posNodeFront->next = New_Node;

5.2后继插入

void Inster_PostionRear_List(Lnode* Head_Node,Node_Data posdata,Node_Data data)
{
	Lnode* posNode = Head_Node->next;
    Lnode* New_Node = Create_New_Node(data);

	if(posNode == NULL)
	{
		printf("此链表为空,插入失败\n");
		return ;
	}
	else
	{
		while(posNode->data != posdata)
		{
			posNode = posNode->next;
			if(posNode == NULL)
			{
				printf("插入失败\n");
				return ;
			}
		}
		New_Node->next = posNode->next;
		posNode->next = New_Node;
	}
	
}

和前驱插入类似。
在这里插入图片描述

①、New_Node->next = posNode->next;
②、posNode->next = New_Node;

6、查找

6.1查找某个值

//查找链表中的某个值 
void Find_CertainValue_List(Lnode* Head_Node,Node_Data value)
{
	Lnode* pMove = Head_Node->next;

	if(pMove == NULL)
	{
		printf("查找失败,链表为空\n");
		return ;
	}
	else
	{
		//遍历整个链表
		while(pMove->data !=  value)
		{
			pMove = pMove->next;
			//遍历结束还未找到
			if(pMove == NULL)
			{
				printf("查找失败,不存在该值\n");
				return ;
			}
		}
		//跳出while表示查找成功
		printf("查找成功\n");
		return ;
	}
}

此查找方法为直接查找,定义指针pMove遍历整个链表

6.2查找某个链表的倒数第n个值

给定一个链表,不知道链表长度,查找此链表倒数第n个值 (前提是链表长度大于n)

//不知道链表长度的情况下(链表长度大于n),查找倒数第n个值
Node_Data Find_Value_List(Lnode* Head_Node,int n)
{
    Lnode* posNode = Head_Node->next;
    Lnode* posNode_Behind_n = Head_Node->next;
    while(n--)
    {
        posNode_Behind_n = posNode_Behind_n->next;
    }
    
    if(posNode == NULL)
    {
        //printf("此链表为空,查找失败\n");
        return -1;
	}
    else
    {
        while(posNode_Behind_n != NULL)
        {
            posNode = posNode->next;
            posNode_Behind_n = posNode_Behind_n->next;
        }
        return posNode->data;
    }
    
}

思路如下:
定义两个指针posNode_Behind_nposNode,二者相隔n个位置,当posNode_Behind_nNULL时,此时posNode所指向的节点就是链表的倒数第n个节点。

7、全部代码测试如下

#include<stdio.h>
#include<malloc.h>

typedef int Node_Data;

typedef struct node{
    Node_Data data;
    struct node* next;
}Lnode;

//创建链表头节点,返回值为struct node*
Lnode* Create_Head_Node()
{
    //动态内存申请
    Lnode* Head_Node = (Lnode *)malloc(sizeof(Lnode));
    if(Head_Node == NULL)
    	return NULL;
    else
    {
	    //初始化头节点
	   // Head_Node->data = 1;  //这个可以随意赋值
	   Head_Node->next = NULL;
	   return Head_Node;
    }
}

//创建新的节点,并给此节点赋值
Lnode* Create_New_Node(Node_Data data)
{
    Lnode* New_Node = (Lnode *)malloc(sizeof(Lnode));
    
    if(New_Node == NULL)
    	return NULL;
    else
    {
	    New_Node->data = data;
	    New_Node->next = NULL;
	    
	    return New_Node;
    }
}

//打印链表
void Printf_List(Lnode* Head_Node)
{
    Lnode* pMove = Head_Node->next;
    
    if(pMove == NULL)
    {
        printf("此链表为空,打印失败\n");
        return ;
    }
    else
    {
        while(pMove != NULL)
        {
            printf("%d->",pMove->data);
            pMove = pMove->next;
        }
        printf("NULL\n");
    }
}

//头插法插入数据
void Insert_Data_List(Lnode* Head_Node,Node_Data data)
{
    Lnode* New_Node = Create_New_Node(data);
    
    if(New_Node == NULL)
    {
        printf("插入失败\n");
        return ;
    }
    else
    {
        New_Node->next = Head_Node->next;
        Head_Node->next = New_Node;
        //printf("插入成功\n");
        return ;
    }
}

//按值删除
void Delete_AccordValue_List(Lnode* Head_Node,Node_Data posdata)
{
    Lnode* posNode = Head_Node->next;
    Lnode* posNodeFornt = Head_Node;
    
    if(posNode == NULL)
    {
        printf("此链表为空,删除失败\n");
        return ;
    }
    else
    {
        while(posNode->data != posdata)
        {
            posNodeFornt = posNode;
            posNode = posNode->next;
            if(posNode == NULL)
            {
                printf("删除失败,不存在该值\n");
                return ;
            }
        }
        posNodeFornt->next = posNode->next;
        free(posNode);
        printf("删除成功\n");
    }
}

//指定位置的前面插入,和按值删除类似
void Inster_PostionPrecursor_List(Lnode* Head_Node,Node_Data posdata,Node_Data data)
{
    Lnode* posNode = Head_Node->next;
    Lnode* posNodeFront = Head_Node;
    Lnode* New_Node = Create_New_Node(data);
    if(posNode == NULL || New_Node == NULL)
    {
        printf("插入失败,此链表为空\n");
        return ;
    }
    else
    {
        while(posNode->data != posdata)
        {
            posNodeFront = posNode;
            posNode = posNode->next;
            if(posNode == NULL)
            {
                printf("插入失败\n");
                return ;
            }
        }
        New_Node->next = posNode;
        posNodeFront->next = New_Node;
       // printf("插入成功\n");
    }
}

void Inster_PostionRear_List(Lnode* Head_Node,Node_Data posdata,Node_Data data)
{
	Lnode* posNode = Head_Node->next;
    Lnode* New_Node = Create_New_Node(data);

	if(posNode == NULL)
	{
		printf("此链表为空,插入失败\n");
		return ;
	}
	else
	{
		while(posNode->data != posdata)
		{
			posNode = posNode->next;
			if(posNode == NULL)
			{
				printf("插入失败\n");
				return ;
			}
		}
		New_Node->next = posNode->next;
		posNode->next = New_Node;
	}
	
}

//查找链表中的某个值 
void Find_CertainValue_List(Lnode* Head_Node,Node_Data value)
{
	Lnode* pMove = Head_Node->next;

	if(pMove == NULL)
	{
		printf("查找失败,链表为空\n");
		return ;
	}
	else
	{
		while(pMove->data !=  value)
		{
			pMove = pMove->next;
			if(pMove == NULL)
			{
				printf("查找失败,不存在该值\n");
				return ;
			}
		}
		printf("查找成功\n");
		return ;
	}
}

//不知道链表长度的情况下(链表长度大于n),查找倒数第n个值
Node_Data Find_List(Lnode* Head_Node,int n)
{
    Lnode* posNode = Head_Node->next;
    Lnode* posNode_Black_n = Head_Node->next;
    while(n--)
    {
        posNode_Black_n = posNode_Black_n->next;
    }
    
    if(posNode == NULL)
    {
        //printf("此链表为空,查找失败\n");
        return -1;
	}
    else
    {
        while(posNode_Black_n != NULL)
        {
            posNode = posNode->next;
            posNode_Black_n = posNode_Black_n->next;
        }
        return posNode->data;
    }
    
}


int main()
{
    Lnode* Head_Node = Create_Head_Node();
    
    Insert_Data_List(Head_Node,1);
    Insert_Data_List(Head_Node,2);
    Insert_Data_List(Head_Node,3);
    Insert_Data_List(Head_Node,4);
    Insert_Data_List(Head_Node,5);
    Insert_Data_List(Head_Node,6);
    Insert_Data_List(Head_Node,7);
	printf("链表内容如下:");
	Printf_List(Head_Node);
	
	printf("\n删除链表中的5:");
    Delete_AccordValue_List(Head_Node,5);
	printf("删除之后,内容如下:");
	Printf_List(Head_Node);

	printf("\n在4的前面插入77:");
	Inster_PostionRear_List(Head_Node,4,77);
	printf("插入数据后,内容如下:");
	Printf_List(Head_Node);

	printf("\n在6的后面插入88:");
	Inster_PostionPrecursor_List(Head_Node,6,88);
	printf("插入数据后,内容如下:");
	Printf_List(Head_Node);

	printf("\n查找链表中的77:");
    Find_CertainValue_List(Head_Node,1);

	printf("\n查找链表中倒数第3个值:");
    printf("%d\n",Find_List(Head_Node,3));

	printf("\n测试结束!!!!\n");
    return 0;
}

运行结果如下:
在这里插入图片描述

END

到这里链表的基本操作已经实现了,下一节我会写一个学生管理系统

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

点灯大师~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值