【数据结构】链表----1.无头单向非循环链表增删查改实现

链表的概念及结构:链表是一种物理存储结构上非连续,非顺序的存储结构.链表通常由连串的节点组成,每个节点包含数据和一或两个指向前一个和后一个节点的指针(链接).
【数据结构】链表----1.无头单向非循环链表增删查改实现_第1张图片
链表的结构形式非常多样(以下3种情况便可组合8种链表结构)

  1. 单向、双向
  2. 带头、不带头
  3. 循环、非循环
    常用的两种结构:
    (1)无头单向非循环链表【数据结构】链表----1.无头单向非循环链表增删查改实现_第2张图片
    (2)带头双向循环链表【数据结构】链表----1.无头单向非循环链表增删查改实现_第3张图片

其中无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。

无头单向非循环链表增删查改代码实现:
SList.h

#pragma once
#include 
#include 
#include 
#include 

typedef int SLTDataType;
typedef struct SListNode
{
	SLTDataType _data;				//保存节点数据
	struct SListNode* _next;		//指向下一个节点
}SListNode;

typedef struct SList
{
	SListNode* _head;			
}SList;
void SListInit(SList* plist);						//链表初始化
void SListDestory(SList* plist);					//链表销毁
SListNode* BuySListNode(SLTDataType x);				//创建新节点
void SListPushFront(SList* plist, SLTDataType x);	//头插
void SListPopFront(SList* plist);					//头删
void SListPushBack(SList* plist, SLTDataType x);	//尾插
void SListPopBack(SList* plist);					//尾删
SListNode* SListFind(SList* plist, SLTDataType x);	//查找指定数据节点
int SListSize(SList* plist);						//节点个数
//在pos的前面插入
void SListInsertFront(SList* plist, SLTDataType pos, SLTDataType x);
//在pos的后面插入
void SListInsertAfter(SList* plist, SLTDataType pos, SLTDataType x);
void SListEraseAfter(SList* plist, SLTDataType pos);//删除指定位置节点
void SListRemove(SList* plist, SLTDataType x);		//删除指定数据节点
void SListPrint(SList* plist);						//打印节点数据
void TstList();										//测试函数

SList.c

#include "SList.h"

//链表初始化,链表头指针赋空
void SListInit(SList* plist)
{
	plist->_head = NULL;
}
//链表销毁,依次释放每个节点
void SListDestory(SList* plist)
{
	assert(plist);			//判断链表是否存在
	SListNode* tmp = NULL;
	while (plist->_head)
	{
		tmp = plist->_head;
		plist->_head = plist->_head->_next;
		free(tmp);
	}
}
//创建新的节点,
SListNode* BuySListNode(SLTDataType x)
{
	SListNode* ptr = NULL;
	ptr = (SListNode*)malloc(sizeof(SLTDataType)+sizeof(SListNode));
	assert(ptr);
	ptr->_data = x;
	ptr->_next = NULL;
	return ptr;
}
//头插
void SListPushFront(SList* plist, SLTDataType x)
{
	assert(plist);
	SListNode* ptr = (SListNode*)malloc(sizeof(SListNode));
	ptr->_data = x;
	ptr->_next = plist->_head;		//原先的头节点作为下一个节点
	plist->_head = ptr;				//将头指向新插入的节点
}
//头删
void SListPopFront(SList* plist)
{
	assert(plist);
	SListNode* tmp;
	tmp = plist->_head;
	if (plist->_head == NULL)
	{
		printf("PopFront Fail(链表为空)\n");
	}
	else
	{
		plist->_head = plist->_head->_next;
		free(tmp);
	}
}
//尾插
void SListPushBack(SList* plist, SLTDataType x)
{
	assert(plist);
	SListNode* ptr = plist->_head;
	//如果链表为空,让头节点指向新节点
	if (plist->_head == NULL)
	{
		plist->_head = BuySListNode(x);		
	}
	else
	{
		//找到链表最后一个节点
		while (ptr->_next)							
		{
			ptr = ptr->_next;
		}
		ptr->_next = BuySListNode(x);
	}
}
//尾删
void SListPopBack(SList* plist)
{
	assert(plist);
	SListNode* ptr = plist->_head;
	//链表为空,直接返回,尾删失败
	if (plist->_head == NULL)
		return;
	//只有一个节点
	else if (plist->_head->_next == NULL)
	{
		free(plist->_head);
		plist->_head = NULL;
	}
	//存在两个及以上节点
	else
	{
		while (ptr->_next->_next)		//由于需要找到倒数第二个节点,所有判断后一个节点的后一个节点是否为空,不需要每走一步保存当前节点
		{
			ptr = ptr->_next;
		}
		free(ptr->_next);
		ptr->_next= NULL;
	}
}
//查找数据为 x 的节点,返回该节点
SListNode* SListFind(SList* plist, SLTDataType x)
{
	assert(plist);
	SListNode* ptr = plist->_head;
	while (ptr)
	{
		//如果当前节点数据等于 x ,返回当前节点
		if (ptr->_data == x)
		{
			return ptr;
			//不等于,则向后走一个节点继续判断
		}  else
			ptr = ptr->_next;
	}
	//如果所有节点的数据都不等于 x ,则返回空
	return NULL;
}
//链表节点个数
int SListSize(SList* plist)
{
	assert(plist);
	int size = 0;
	SListNode* tmp = plist->_head;
	while (tmp)
	{
		tmp = tmp->_next;
		size++;
	}
	return size;
}
//在pos的前面插入
void SListInsertFront(SList* plist, SLTDataType pos, SLTDataType x)
{
	assert(plist || pos <= SListSize(plist));
	int i = 1;								//用于确定走到第几个节点
	SListNode* ptr = plist->_head;
	SListNode* cur = ptr;
	while (i < pos)
	{
		cur = ptr;							//因为要用到pos前的一个节点,所以每走一步保存前一个的节点
		ptr = ptr->_next;
		i++;
	}
	//将数据 x 放入新创建好的节点
	SListNode* NewNode = BuySListNode(x);
	NewNode->_next = ptr;					//新节点指向pos处的节点ptr
	cur->_next = NewNode;					//pos前的节点指向新插入的节点
}
//在pos的后面插入
void SListInsertAfter(SList* plist, SLTDataType pos, SLTDataType x)
{
	assert(plist || pos <= SListSize(plist));

	int i = 1;								//用于确定走到第几个节点
	SListNode* ptr = plist->_head;
	SListNode* cur = ptr;
	while (i <= pos)
	{
		cur = ptr;							//因为要用到pos,及pos后一个节点,每走一步保存前一个节点
		ptr = ptr->_next;
		i++;
	}
	//将数据 x 放入新创建好的节点
	SListNode* NewNode = BuySListNode(x);
	NewNode->_next = ptr;					//新节点指向pos处的下一个节点ptr
	cur->_next = NewNode;					//pos处的节点指向新插入的节点
}
//删除 pos 处的节点
void SListEraseAfter(SList* plist, SLTDataType pos)
{
	assert(plist || pos <= SListSize(plist));
	SListNode* tmp = plist->_head;				//保存pos处的节点
	SListNode* ptr = NULL;						//保存pos的前一个节点
	//如果只有一个节点
	if (plist->_head->_next == NULL)
	{
		free(plist->_head);
		plist->_head = NULL;
	}
	else
	{
		for (int i = 1; i < pos; i++)
		{
			ptr = tmp;
			tmp = tmp->_next;
		}
		ptr->_next = tmp->_next;				//pos的前一个节点 ptr 指向 pos 的后一个节点
		free(tmp);								//删除 pos 处的节点
	}
}
//删除数据为 x 的节点
void SListRemove(SList* plist, SLTDataType x)
{
	assert(plist);
	SListNode* ptr = plist->_head;
	for (int i = 0; i <= SListSize(plist);++i,ptr = ptr->_next)
	{
		if (ptr->_data == x)
		{
			SListEraseAfter(plist, i);
		}
	}
}
//打印链表数据
void SListPrint(SList* plist)
{
	assert(plist);
	SListNode* ptr = plist->_head;
	while (ptr)
	{
		printf("%d ", ptr->_data);
		ptr = ptr->_next;
	}
	printf("\n");
}
//测试函数
void TestList()
{
	SList plist;
	SListInit(&plist);		//链表初始化
	//尾插测试
	SListPushBack(&plist, 5);
	SListPushBack(&plist, 6);
	SListPushBack(&plist, 7);
	SListPushBack(&plist, 8);
	SListPrint(&plist);
	//头插测试
	SListPushFront(&plist, 4);
	SListPushFront(&plist, 3);
	SListPushFront(&plist, 2);
	SListPushFront(&plist, 1);
	SListPrint(&plist);
	//尾删测试
	SListPopBack(&plist);
	SListPrint(&plist);
	//头删测试
	SListPopFront(&plist);
	SListPrint(&plist);
	
	SListInsertAfter(&plist, 3, 10);
	SListPrint(&plist);
	SListInsertFront(&plist, 4, 11);
	SListPrint(&plist);

	SListEraseAfter(&plist, 4);
	SListPrint(&plist);

	SListRemove(&plist, 4);
	SListPrint(&plist);

	SListDestory(&plist);
}

main.c

#include "SList.h"

int main()
{
	TestList();
	system("pause");
	return 0;
}

测试结果:
【数据结构】链表----1.无头单向非循环链表增删查改实现_第4张图片

你可能感兴趣的:(数据结构)