数据结构_非常方便的链表
✨✨所属专栏:数据结构✨✨
✨✨作者主页:嶔某✨✨
链表是线性表的一种,是⼀种物理存储结构上⾮连续、⾮顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
和顺序表差不多,用结构体定义一个节点,包括存储的数据和下一个节点的地址。
这里我们写几个接口:尾插,头插,尾删,头删,查找元素,指定位置插入,指定位置删除,销毁。
SList.h
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SList_Datatype;
typedef struct SList_Node
{
	SList_Datatype Data;
	struct SList_Node* Next;
}STL_Node;
void SLTPrint(STL_Node* phead);
//尾插
void SLTPushBack(STL_Node** pphead, SList_Datatype x);
//头插
void SLTPushFront(STL_Node** pphead, SList_Datatype x);
//尾删
void SLTPopBack(STL_Node** pphead);
//头删
void SLTPopFront(STL_Node** pphead);
//查找
STL_Node* SLTFind(STL_Node* phead, SList_Datatype x);
//在指定位置之前插入数据
void SLTInsert(STL_Node** pphead, STL_Node* pos, SList_Datatype x);
//在指定位置之后插入数据
void SLTInsertAfter(STL_Node* pos, SList_Datatype x);
//删除pos节点
void SLTErase(STL_Node** pphead, STL_Node* pos);
//删除pos之后的节点
void SLTEraseAfter(STL_Node* pos);
//销毁链表
void SListDesTroy(STL_Node** pphead); 
SList.c
打印:
(不改变实参)传一级指针,新建立一个头节点pur,用while循环每次循环打印pur里面的数据,并将pur->next赋给pur。以pur != NULL为循环终止条件。
新建节点:
创建一个newnode指针指向一个新开辟的节点,将数据x放进data,将next置空。
尾插:
(要改变实参)传一个二级指针,用新建节点函数新建一个newnode。这里分情况:
(1)如果*pphead为空,即这个链表没有节点就直接将newnode赋给pphead。
(2)这里要先找尾,定义一个ptail指针首先指向*pphead,之后用whlie循环进行找尾。将ptail->next指向newnode。
头插:
头插比较简单(因为不需要找尾),传一个二级指针,新建一个节点将newnode的next指向*pphead,将*pphead指向newnode。就完成了头节点的替换。
尾删:
传二级指针,尾删和尾插差不多的,只是在找尾的时候需要两个指针,最后分别指向尾节点和尾节点的前一个节点。这里就不多叙述了。
头删:
传二级指针,新建一个指针指向第二个节点,将第一个节点释放掉后,将*pphead指向先前备份好的第二个节点。
查找元素:
传一级指针,新建一个指针指向phead循环遍历链表里面的数据,得到结果返回相应节点的指针,否则返回空指针。
在指定位置前/后插入数据:
因为前插比较复杂,这里只讲前插。
传二级指针,先新建一个节点将数据放进去,分两种情况
(1)pos为头指针:这里直接调用头插的函数。
(2)pos不为头指针:新建指针prev,这里还是用while循环找pos前一个节点的指针,循环结束条件为prev->next != pos 、之后将prev的next指向新节点,新节点的next指向pos;
删除pos节点/删除pos之后的节点(第二个我觉得没必要):
这里讲第一个,传二级指针,分两种情况
(1)pos == *pphead:直接调用头插。
(2)pos != *pphead:新建指针prev用while循环找尾节点的前一个节点(不多讲)将prev的next指向pos的next,此时pos就不在链表里面了,只需要将它的空间释放掉,将指针置空就ok了。
销毁链表:
传二级指针,用while在循环里面将当前*pphead指向的空间释放,再将*pphead指向,下一个节点,结束条件为*pphead != NULL,循环结束后记得将*pphead置空(这是个好习惯)
下面参考代码附上:
#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"
void SLTPrint(STL_Node* phead)
{
	STL_Node* pur = phead;
	while (pur)
	{
		printf("%d->", pur->Data);
		pur = pur->Next;
	}
	printf("NULL\n");
}
STL_Node* SLTBuyNode(SList_Datatype x)
{
	STL_Node* newnode = (STL_Node*)malloc(sizeof(STL_Node));
	if (newnode == NULL)
	{
		perror("malloc is fail!");
		exit(1);
	}
	newnode->Data = x;
	newnode->Next = NULL;
	return newnode;
}
void SLTPushBack(STL_Node** pphead, SList_Datatype x)
{
	assert(pphead);
	STL_Node* newnode = SLTBuyNode(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		STL_Node* ptail = *pphead;
		while (ptail->Next)
		{
			ptail = ptail->Next;
		}
		ptail->Next = newnode;
	}
}
void SLTPushFront(STL_Node** pphead, SList_Datatype x)
{
	assert(pphead);
	STL_Node* newnode = SLTBuyNode(x);
	newnode->Next = *pphead;
	*pphead = newnode;
}
void SLTPopBack(STL_Node** pphead)
{
	assert(pphead&&*pphead);
	if ((*pphead)->Next == NULL)
	{
		free(pphead);
		pphead = NULL;
	}
	STL_Node* prve = *pphead;
	STL_Node* ptail = *pphead;
	while (ptail->Next)
	{
		prve = ptail;
		ptail = ptail->Next;
	}
	free(ptail);
	ptail = NULL;
	prve->Next = NULL;
}
void SLTPopFront(STL_Node** pphead)
{
	assert(pphead&&*pphead);
	STL_Node* tmp = (*pphead)->Next;
	free(*pphead);
	*pphead = tmp;
}
STL_Node* SLTFind(STL_Node* phead, SList_Datatype x)
{
	STL_Node* pur = phead;
	while (pur)
	{
		if (pur->Data == x)
		{
			return pur;
		}
		pur = pur->Next;
	}
	return NULL;
}
//在指定位置之前插入数据
void SLTInsert(STL_Node** pphead, STL_Node* pos, SList_Datatype x)
{
	assert(pphead&&*pphead);
	assert(pos);
	STL_Node* newnode = SLTBuyNode(x);
	if (*pphead == pos)
	{
		SLTPushFront(pphead,x);
		free(newnode);
		newnode = NULL;
	}
	else
	{
		STL_Node* prve = *pphead;
		while (prve->Next != pos)
		{
			prve = prve->Next;
		}
		prve->Next = newnode;
		newnode->Next = pos;
	}
}
//在指定位置之后插入数据
void SLTInsertAfter(STL_Node* pos, SList_Datatype x)
{
	assert(pos);
	STL_Node* newnode = SLTBuyNode(x);
	newnode->Next = pos->Next;
	pos->Next = newnode;
}
//删除pos节点
void SLTErase(STL_Node** pphead, STL_Node* pos)
{
	assert(pphead&&*pphead);
	assert(pos);
	if (pos == *pphead)
		SLTPopFront(pphead);
	else
	{
		STL_Node* prev = *pphead;
		while (prev->Next != pos)
		{
			prev = prev->Next;
		}
		prev->Next = pos->Next;
		free(pos);
		pos = NULL;
	}
}
//删除pos之后的节点
void SLTEraseAfter(STL_Node* pos)
{
	assert(pos&&pos->Next);
	STL_Node* del = pos->Next;
	pos->Next = del->Next;
	free(del);
	del = NULL;
}
//销毁链表
void SListDesTroy(STL_Node** pphead)
{
	assert(pphead && *pphead);
	while (*pphead)
	{
		STL_Node* next = (*pphead)->Next;
		free(*pphead);
		*pphead = next;
	}
	*pphead = NULL;
}
 
本期博客到这里就结束了,如果有什么错误,欢迎指出,如果对你有帮助,请点个赞,谢谢!
                    
                
                
            
        
浙公网安备 33010602011771号