单链表基本操作--数据结构

单链表基本操作–数据结构

链表是一种物理存储结构上非连续非顺序的数据存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序来形成的。
单链表分为两种:带头节点和不带头结点。在这里,主要介绍不带头结点的单链表的基本操作。

头文件:SList.h

typedef int SDataType;
typedef struct SListNode//定义结点
{
	SDataType data;//值域
	//指针域指针,指向下一个结构体
	struct SListNode* pNext;
}Node;
typedef struct SList//链表
{
	Node* pHead;//链表结构链表中的一个结点
}SList;
void SListInit(SList* pl); //初始化链表
Node* BuySListNode(SDataType data);//开辟一个结点
void SListPushBack(SList* pl, SDataType data);//尾插
void SListPopBack(SList* pl); //尾删

void SListPushFront(SList* pl, SDataType data);//头插
void SListPopFront(SList* pl);//头删

//在链表中查找值为data的结点,找到返回该结点的地址,否则返回空
Node* SListFind(SList* pl, SDataType data);
//在链表结点pos位置后置入值为data的结点
void SListInsertAfter(Node* pos, SDataType data);
//删除链表中位置在pos的结点
void SListErase(SList* pl, Node* pos);

int SListSize(SList* pl);//获取链表中有效结点的个数
int SListEmpty(SList* pl);//检测链表是否为空

Node* SListFront(SList* pl);//获取链表第一个结点
Node* SListBack(SList* pl);//获取链表的第二个结点

void PrintSList(SList* pl);//打印链表
void DestorySList(SList* pl);//销毁 

源文件:SList.c

#include "SList.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

void SListInit(SList* pl) //初始化
{
	assert(pl);
	pl->pHead = NULL;
}


Node* BuySListNode(SDataType data) //开辟一个结点
{
	Node* pNode = (Node*)malloc(sizeof(Node));
	if (NULL == pNode)
	{
		assert(0);
		return NULL;
	}
	pNode->data = data;
	pNode->pNext = NULL;
	return pNode;
}

void SListPushBack(SList* pl, SDataType data) //尾插
{
	Node* pNewNode = NULL;//定义新的结点
	Node* pCur = NULL; //将头指针赋值给它

	assert(pl);

	pNewNode = BuySListNode(data);
	pCur = pl->pHead;

	//空链表
	if (NULL == pl->pHead)
		pl->pHead = pNewNode;
	else
	{
		while (pCur->pNext)
		{
			pCur = pCur->pNext;
		}
		pCur->pNext = pNewNode;
	}
}
void SListPopBack(SList* pl) //尾删
{
	assert(pl);

	if (NULL == pl->pHead) //空链表
	{
		printf("没有可以删除的项\n");
		return;
	}
	else if (NULL == pl->pHead->pNext) //只有一个结点
	{
		free(pl->pHead);
		pl->pHead = NULL;
	}
	
	方法一:找到倒数第二个结点
	else //有两个以上的结点
	{
		Node* pTailNode = pl->pHead; 
		while (pTailNode->pNext->pNext)//找到倒数第二个结点
		{
			pTailNode = pTailNode->pNext;
		}
		free(pTailNode->pNext);
		pTailNode->pNext = NULL;
	}

	方法二:找到倒数第一个结点,并保存前一个结点
	else
	{
		Node* pTailNode = pl->pHead;
		Node* pPreNode = NULL;
		while (pTailNode->pNext)
		{
			pPreNode = pTailNode;
			pTailNode = pTailNode->pNext;
		}
		free(pTailNode);
		pPreNode->pNext = NULL;
	}
}
void SListPushFront(SList* pl, SDataType data)
{
	Node* pNewNode = NULL;
	assert(pl);

	pNewNode = BuySListNode(data);
	pNewNode->pNext = pl->pHead;
	pl->pHead = pNewNode;
}
void SListPopFront(SList* pl)
{
	assert(pl);
	if (NULL == pl->pHead)
	{
		return;
	}
	else
	{
		Node* pDelNode = pl->pHead;
		pl->pHead = pDelNode->pNext;
		free(pDelNode);
	}
}
// 在链表中查找值为data的节点,找到返回该节点的地址,否则返回空
Node* SListFind(SList* pl, SDataType data)
{
	Node* pCur = pl->pHead;
	assert(pl);
	while (pCur)
	{
		if (pCur->data == data)
		{
			return pCur;
		}
		else
		{
			pCur = pCur->pNext;
		}
	}
	return NULL;
}
void SListInsertAfter(Node* pos, SDataType data)
{
	Node* pNewNode = NULL;
	if (NULL == pos)
		return;
	pNewNode = BuySListNode(data);
	pNewNode->pNext = pos->pNext;
	pos->pNext = pNewNode;
}
void SListErase(SList* pl, Node* pos)
{
	Node* pDelNode = NULL;
	assert(pl);
	if (NULL == pl->pHead || NULL == pos)
		return;
	//pos刚好在第一个结点的位置
	if (pos == pl->pHead)
	{
		pl->pHead = pos->pNext;
		free(pos);
		return;
	}
	//pos不在第一个位置
	pDelNode = pl->pHead;
	while (pDelNode->pNext != pos)
	{
		pDelNode = pDelNode->pNext;
	}
	pDelNode->pNext = pos->pNext;
	free(pos);
}
void PrintSList(SList* pl) //打印链表
{
	Node* pCur = NULL;
	assert(pl);
	pCur = pl->pHead;
	while (pCur)
	{
		printf("%d-->", pCur->data);
		pCur = pCur->pNext;
	}
	printf("NULL\n");
}
void DestorySList(SList* pl) //销毁链表
{
	Node* pCur = NULL;
	assert(pl);

	pCur = pl->pHead;
	while (pCur)
	{
		pl->pHead = pCur->pNext;
		free(pCur);
		pCur = pl->pHead;
	}
	pl->pHead = NULL;
}
int SListSize(SList* pl)
{
	assert(pl);
	Node* pCur = NULL;
	int count = 0;

	pCur = pl->pHead;
	while (pCur)
	{
		count++;
		pCur = pCur->pNext;
	}
	return count;
}
int SListEmpty(SList* pl)
{
	assert(pl);
	return NULL == pl->pHead;
}
Node* SListFront(SList* pl)
{
	assert(pl);
	return pl->pHead;
}
Node* SListBack(SList* pl)
{
	Node* pCur = pl->pHead;
	assert(pl);
	assert(pl->pHead);

	pCur = pl->pHead;
	while (pCur->pNext)
	{
		pCur = pCur->pNext;
	}
	return pCur;
}

测试文件:test.c

#include "SList.h"
#include <stdio.h>
void TestSList1()
{
	SList link;//定义
	SListInit(&link);//初始化
	//PrintSList(&link);//打印

	SListPushBack(&link, 1);//尾插
	SListPushBack(&link, 2);
	SListPushBack(&link, 3);
	SListPushBack(&link, 4);
	SListPushBack(&link, 5);
	SListPushBack(&link, 6);
	SListPushBack(&link, 7);
	SListPopBack(&link); //尾删

	SListPushFront(&link, 0);//头插
	SListPushFront(&link, 8);
	SListPopFront(&link);//头删

    //在链表结点pos位置后置入值为data的结点
	SListInsertAfter(SListFind(&link,4),9);
	//删除链表中位置在pos的结点
	SListErase(&link, SListFind(&link,3));
	
    //获取链表中有效结点的个数
	printf("%d\n",SListSize(&link));
	//检测链表是否为空
	printf("%d\n",SListEmpty(&link));
	
	SListFront(&link);//获取链表第一个结点
	SListBack(&link);//获取链表的第二个结点

	PrintSList(&link);//打印
    DestorySList(&link);//销毁
}
int main()
{
	TestSList1();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值