C语言数据结构——链表

一.要学好链表,首先要理清链表的结构。

接下来给大家理一下链表思路。
1.逻辑结构
在这里插入图片描述
可以看出,与顺序表不同,链表是像链条一样一个一个连在一起,在这里我们用指针来实现。

2.逻辑结构我们不好理解,我们来用物理结构给大家展示
在这里插入图片描述
上一个结构体存下一个地址,下一个再存下下一个,链式环环相扣。

二 . 我们将逻辑理清,接下来就到了代码实现

1.将存储每一个数据的结构体声明一下

typedef int StdDatatype; //为了我们以后可以存储其他类型的链表,我们将数据类型typedef一下。
struct StdlistNode
{
	StdDatatype data;   //存储这个数据
	struct StdlistNode* Next;    //相当于箭头指向下一个数据的结构体
};
typedef struct StdlistNode STDNode;  //将结构体的名字重定义一下

2.打印一下链表。

void PrintStlist(STDNode* plist)   //打印链表
{
	STDNode* tail = plist;
	while (tail != NULL)
	{
		printf("%d->", tail->data);
		tail = tail->Next;
	}
	printf("NULL");
}

3.由于我们每次都需要开辟一块空间,比较麻烦,我们干脆自定义一个开辟空间的函数。

STDNode* Buymemory(StdDatatype x)
{
	STDNode* now = (STDNode*)malloc(sizeof(StdDatatype));
	now->data = x;
	now->Next = NULL;
	return now;
}

4.准备工作完毕,和顺序表一样,我们需要进行头插

void StdlistPushFront(STDNode** plist, StdDatatype x)    
{
	STDNode* now = Buymemory(x);   //开辟一块空间 里面存储x
	now->Next = *plist;  //将NEXT的地址和链表连接起来。
	*plist = now;  //将新的链表赋值给之前的链表完成头插
}

5.接下来进行尾插

尾插比头插相对来说复杂一点,首先我们需要先找到最后一个链表,之后再插入数据

void StdlistPushBack(STDNode** plist, StdDatatype x)    
{
	STDNode* now = Buymemory(x);
	if (*plist == NULL)  //如果链表中没有元素,则直接赋值即可
	{
		*plist = now;
	}
	else
	{
		STDNode* tail = *plist; 
		while (tail->Next != NULL)  //寻找尾部元素
		{
			tail = tail->Next;
		}
		tail->Next = now;   //找到后将链表赋值给尾部的下一个结构                                                       
	}
}
                                             

6.接下来头删。

注意VS2019中free释放空间需要写成void形式。

void StdlistPopFront(STDNode** plist)    
{
	if (*plist == NULL)  //如果链表为空,直接结束
		return;
	if ((*plist)->Next == NULL)  //判断如果链表只有一个元素
	{
		STDNode* mid = (*plist)->Next;  //引入中间结构体,存储下一块
		void free(void* mid);   //将下一块NULL内存删除
		*plist = NULL;  //将头部置为空
	}
	else  //正常情况下
	{
		STDNode* mid = (*plist)->Next;  //引入中间变量存储下一块内存单元
		void free(void* plist);  //释放头部内存
		*plist = mid;   //将中间变量赋值给链表。
	}
}

7.尾删。

尾删相对来说就比较简单,我们只需要找到尾部将下一个NULL释放掉,然后将尾部赋值为NULL。

void StdlistPopBack(STDNode** plist)  //尾删
{
	if (*plist == NULL)//如果为空链表直接返回
		return;
	if ((*plist)->Next == NULL) //如果链表只有一个元素。
	{
		STDNode* mid = (*plist)->Next;//将下一块NULL释放,然后将第一块赋值为NULL
		void free(void* mid);
		*plist = NULL;
	}
	else  //正常情况下
	{
		STDNode* mid = NULL;  
		STDNode* tail = *plist;
		while (tail->Next != NULL)  //寻找尾部元素
		{
			mid = tail;
			tail = tail->Next;
		}
		void free(void* tail);  //找到后释放NEXT NULL
		mid->Next = NULL;  //将尾部元素赋值为NULL
	}
	              
}

8.寻找某个元素

STDNode* StdlistFind(STDNode* plist, StdDatatype x)   //寻找某元素
{
	STDNode* Pop = plist;
	while (Pop->data != x&&Pop->Next !=NULL)  //寻找,如果不是一直往下走
	{
		Pop = Pop->Next;
	}
	if (Pop->data == x)   //如果找到了则返回目标元素
		return Pop;
	else                     //找不到则返回NULL
		return NULL;
}

9.再找到的某个元素前插入某元素

void StdlistInsert(STDNode** plist, STDNode* Pop, StdDatatype x)   
{
	if (*plist == Pop)  //如果首元素就是Pop,则相当于头插
	{
		StdlistPushFront(plist, x);
	}
	else  //正常情况下
	{
		STDNode* now = Buymemory(x); //拓展一个内存空间存储x
		STDNode* mid = *plist;  //引入中间链表
		while (mid->Next  != Pop)  寻找元素
		{
			mid = mid->Next;
		}
		mid->Next = now;  //将上一个元素的Next与now链接
		now->Next = Pop;  //将now的next与下一个链表链接
	}
}

10.在指定元素后插入某元素

void StdlistErase(STDNode** plist, STDNode* Pop, StdDatatype x)
{
	STDNode* now = Buymemory(x); //开辟一块空间存储x
	STDNode* mid = *plist;
	while (mid != Pop)  //寻找Pop
	{
		mid = mid->Next; 
	}
	if (mid->Next == NULL) //找到后如果Pop为最后一个元素直接尾插即可
	{
		StdlistPushBack(plist, x);
	}
	else    //正常情况下
	{
		STDNode* tail = mid->Next;    
		mid->Next = now;  
		now->Next = tail;
	}
}

整体代码实现

1.Slist.h 声明函数,及头文件

#pragma once
#define _CRT_SECURE_NO_WAR
#include<stdio.h>
#include<stdlib.h>
typedef int StdDatatype;
struct StdlistNode
{
	StdDatatype data;
	struct StdlistNode* Next;
};
typedef struct StdlistNode STDNode;
void StdlistPushBack(STDNode** plist, StdDatatype x);  //尾插
void PrintStlist(STDNode* plist);  //打印
void StdlistPushFront(STDNode** plist, StdDatatype x); //头插
void StdlistPopFront(STDNode** plist);  //头删
void StdlistPopBack(STDNode** plist);  //尾删
void StdlistInsert(STDNode** plist, StdDatatype x);  //前插
void StdlistErase(STDNode** plist, StdDatatype x);  //后插
STDNode* StdlistFind(STDNode* plist, StdDatatype x);  //查找

2.Slist.c 函数具体实现

#include "Slist.h"              
void PrintStlist(STDNode* plist)   //打印链表
{
	STDNode* tail = plist;
	while (tail != NULL)
	{
		printf("%d->", tail->data);
		tail = tail->Next;
	}
	printf("NULL");
}
void StdlistPushFront(STDNode** plist, StdDatatype x)    //头插
{
	STDNode* now = Buymemory(x);   
	now->Next = *plist;
	*plist = now;
}
void StdlistPushBack(STDNode** plist, StdDatatype x)    //尾插
{
	STDNode* now = Buymemory(x);
	if (*plist == NULL)
	{
		*plist = now;
	}
	else
	{
		STDNode* tail = *plist;
		while (tail->Next != NULL)
		{
			tail = tail->Next;
		}
		tail->Next = now;
	}
}

void StdlistPopFront(STDNode** plist)    //头删
{
	if (*plist == NULL)
		return;
	if ((*plist)->Next == NULL)
	{
		STDNode* mid = (*plist)->Next;
		void free(void* mid);
		*plist = NULL;
	}
	else
	{
		STDNode* mid = (*plist)->Next;
		void free(void* plist);
		*plist = mid;
	}
}

void StdlistPopBack(STDNode** plist)  //尾删
{
	if (*plist == NULL)
		return;
	if ((*plist)->Next == NULL)
	{
		STDNode* mid = (*plist)->Next;
		void free(void* mid);
		*plist = NULL;
	}
	else
	{
		STDNode* mid = NULL;
		STDNode* tail = *plist;
		while (tail->Next != NULL)
		{
			mid = tail;
			tail = tail->Next;
		}
		void free(void* tail);
		mid->Next = NULL;
	}
	              
}

STDNode* StdlistFind(STDNode* plist, StdDatatype x)   //寻找某元素
{
	STDNode* Pop = plist;
	while (Pop->data != x&&Pop->Next !=NULL)
	{
		Pop = Pop->Next;
	}
	if (Pop->data == x)
		return Pop;
	else
		return NULL;
}

void StdlistInsert(STDNode** plist, STDNode* Pop, StdDatatype x)    //Pop的前方插入x
{
	if (*plist == Pop)
	{
		StdlistPushFront(plist, x);
	}
	else
	{
		STDNode* now = Buymemory(x);
		STDNode* mid = *plist;
		while (mid->Next  != Pop)
		{
			mid = mid->Next;
		}
		mid->Next = now;
		now->Next = Pop;
	}
}

void StdlistErase(STDNode** plist, STDNode* Pop, StdDatatype x)
{
	STDNode* now = Buymemory(x);
	STDNode* mid = *plist;
	while (mid != Pop)
	{
		mid = mid->Next;
	}
	if (mid->Next == NULL)
	{
		StdlistPushBack(plist, x);
	}
	else
	{
		STDNode* tail = mid->Next;
		mid->Next = now;
		now->Next = tail;
	}
}

3.text.c 操作文件

#include "Slist.h"
void TextSlist()
{
	STDNode* plist = NULL;
	StdlistPushFront(&plist, 0);
	StdlistPushBack(&plist, 1);
	StdlistPushBack(&plist, 2);
	StdlistPushBack(&plist, 3);
	StdlistPushBack(&plist, 4);
	StdlistPushBack(&plist, 5);
	StdlistPushBack(&plist, 6);
	/*StdlistPopFront(&plist);
	StdlistPopBack(&plist);*/
	/*STDNode* Pop = StdlistFind(plist, 6);*/
	/*StdlistInsert(&plist, Pop,30);*/
	STDNode* Pop = StdlistFind(plist, 6);
	StdlistErase(&plist, Pop, 30);
	PrintStlist(plist);
}
int main()
{
	TextSlist();
	return 0;
}

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

dataowu

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

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

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

打赏作者

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

抵扣说明:

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

余额充值