单链表的详解

目录

什么是单链表

创建单链表

单链表的尾插

单链表的尾删

单链表的头插

单链表的头删

单链表查找 (和修改)


什么是单链表

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个节点的构成:(元素+指针) 元素就是存储数据的存储单元,指针就是连接每个节点的地址数据。

 

 

创建单链表

typedef int SListDate;
//单链表的结构定义 
 typedef struct SListNode
{
	 SListDate	data;//数据

	struct SListNode* next;//结构体指针 next 

}SListNode;

//创建节点(动态开辟)
SListNode* BuySListNode(SListDate x)
{
	SListNode* node =(SListNode*)malloc(sizeof(SListNode));
	node->data = x;
	node->next = NULL;
	return node;
}

单链表的尾插

可以分为:链表为不为空, 为空开辟一个节点,非空找尾

 链表非空

 

 

 

注意我这里的测试接口是定义了一个指针,后面的函数调用时要传二级指针 

void TestList1()
{
	SListNode* plist = NULL;
	SListPushBack(&plist,1);//注意是二级指针
}
int main()
{
	TestList1();
	return 0;
}

 

void SListPushBack(SListNode**pplist, SListDate x)
{
	SListNode* newnode = BuySListNode(x);
     //如果是空链表
	if (*pplist == NULL)
	{
		*pplist = newnode;
	}
	else
	{
		//尾插 ->找尾
		SListNode* tail = *pplist;//先找到头(tail)
		while (tail->next != NULL)
		{
			tail = tail->next;//类似数组中++的作用
                              //tail = tail->next找到下一个节点的地址给给tail  
		}                       
		tail->next = newnode;
	}
}

单链表的尾删

有以下几种情况:1.没有节点(没有可删的)
                            2, 只有1个节点(直接free)
                            3.多个节点

 多个节点先找尾

void SListPopBack(SListNode**pplist)
{
	//1.没有节点
	//2, 只有1个节点
	//3.多个节点
	if (*pplist == NULL)//空链表(没有节点)没有可删的
	{
		return ;
	}
	//找尾
	else if ((*pplist)->next == NULL)//只有一个节点free掉开辟的那个节点
	{                                
		free(*pplist);
		*pplist = NULL;
	}
	else
	{
		SListNode* prev = NULL;
		SListNode* tail = *pplist;
		while (tail->next != NULL)
		{
			prve = tail;
			tail = tail->next;
		}
		free(tail);
		tail = NULL;
		prve->next = NULL;
	}	
}

单链表的头插

 

void SListPushFort(SListNode** pplist, SListDate x)
{
	SListNode* newnode = BuySListNode(x);
	newnode->next = *pplist;//头的地址 plist
	*pplist = newnode;// newnode给给*plist成为新的表头
}

单链表的头删

链表为空,或非空

 

 

void SListPopFort(SListNode** pplist)
{
	//找头
	if (*pplist == NULL)
	{
		return;
	}
	else
	{
		SListNode* next = (*pplist)->next;//先存一下要头删的地址
		free(*pplist);
		*pplist = next;
	}
}

单链表查找 (和修改)

SListNode* SListFind(SListNode* plist, SListDate x)
{
	SListNode* cur = plist;
	//while(cur != NULL)等价于while(cur)
	while (cur)//遍历链表
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

修改

	SListNode* pos = SListFind(plist, 6);//要查找的数字
	 if (pos == NULL)
	 {
		 printf("没有找到\n");
	 }
	 else
	 {
		
		 printf("找到了\n");
		 pos->data = 30;//修改
	 }
	 //SListPrint(plist);
}

单链表打印

void SListPrint(SListNode*plist)
{
	SListNode* cur = plist;
	while (cur != NULL)
	{
		printf("%d->",cur->data);
		cur = cur->next;//next 结构体指针 
      	                //找到下一个不为空的节点(的地址) 并赋值过去
	}
	printf("NULL");
	printf("\n");
}

 

完整测试代码

linklist.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>


typedef int SListDate;
//单链表的结构定义 
 typedef struct SListNode
{
	 SListDate	data;//数据

	struct SListNode* next;//结构体指针 next 
	
}SListNode;
 //单向+不带头+不循环

 //打印链表
 void SListPrint(SListNode*plist);
 //尾插
 void SListPushBack(SListNode**pplist, SListDate x);
 //头插
 void SListPushFort(SListNode**pplist, SListDate x);

 //尾删
 void SListPopBack(SListNode**pplist);
 //头删
 void SListPopFort(SListNode**pplist);
 //单链表查找
 SListNode* SListFind(SListNode* plist, SListDate x);

linklist.c

#include"linklist.h"

void SListPrint(SListNode*plist)
{
	SListNode* cur = plist;
	while (cur != NULL)
	{
		printf("%d->",cur->data);
		cur = cur->next;//next 结构体指针 
      	                //找到下一个不为空的节点(的地址) 并赋值过去
	}
	printf("NULL");
	printf("\n");
}
//创建节点
SListNode* BuySListNode(SListDate x)
{
	SListNode* node =(SListNode*)malloc(sizeof(SListNode));
	node->data = x;
	node->next = NULL;
	return node;
}
void SListPushBack(SListNode**pplist, SListDate x)
{
	SListNode* newnode = BuySListNode(x);
	//如果是空链表
	if (*pplist == NULL)
	{
		*pplist = newnode;
	}
	else
	{
		//尾插 ->找尾
		SListNode* tail = *pplist;//先找到头(tail)
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}
}
void SListPushFort(SListNode** pplist, SListDate x)
{
	SListNode* newnode = BuySListNode(x);
	newnode->next = *pplist;//头的地址 plist
	*pplist = newnode;// newnode给给*plist成为新的表头
}
void SListPopBack(SListNode**pplist)
{
	//1.没有节点
	//2, 只有1个节点
	//3.多个节点
	if (*pplist == NULL)//空链表(没有节点)没有可删的
	{
		return ;
	}
	//找尾
	else if ((*pplist)->next == NULL)//只有一个节点free掉开辟的那个节点
	{                                 //
		free(*pplist);
		*pplist = NULL;
	}
	else
	{
		SListNode* prve = NULL;
		SListNode* tail = *pplist;
		while (tail->next != NULL)
		{
			prve = tail;
			tail = tail->next;
		}
		free(tail);
		tail = NULL;
		prve->next = NULL;
	}	
}
void SListPopFort(SListNode** pplist)
{
	//找头
	if (*pplist == NULL)
	{
		return;
	}
	else
	{
		SListNode* next = (*pplist)->next;//先存一下要头删的地址
		free(*pplist);
		//next 里面存的是头删的地址->下一个节点的地址
		*pplist = next;
	}
}
SListNode* SListFind(SListNode* plist, SListDate x)
{
	SListNode* cur = plist;
	//while(cur != NULL)等价于while(cur)
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}
void SListInsertAfter(SListNode* pos, SListDate x)
{
	assert(pos);
	SListNode* newnode = BuySListNode(x);
	 newnode->next = pos->next;
	  pos->next = newnode;
}

test.c

void TestList1()
{
	SListNode* plist = NULL;
	SListPushFort(&plist,1);//注意是二级指针
	SListPushFort(&plist,2);
	SListPushFort(&plist,3);
	SListPushFort(&plist,4);

	//SListPrint(plist);


    SListPushFort(&plist,5);
	SListPushFort(&plist, 4);
	SListPushFort(&plist, 3);

	//SListPopBack(&plist);
	//SListPopBack(&plist);
	//SListPopBack(&plist);
	//SListPopBack(&plist);
	//SListPopBack(&plist);

	SListPrint(plist);
	SListPrint(plist);


}
void  TestList2()
{
	SListNode* plist = NULL;
	SListPushBack(&plist, 1);//注意是二级指针
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPushBack(&plist, 4);

	SListPrint(plist);

	SListNode* pos = SListFind(plist, 6);//要查找的数字
	 if (pos == NULL)
	 {
		 printf("没有找到\n");
	 }
	 else
	 {
		
		 printf("找到了\n");
		 //pos->data = 30;//修改
	 }
	 SListPrint(plist);
}

int main()
{
	TestList1();
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值