数据结构之实现链表的基本操作 增减删改

版权声明:转载请联系 :[email protected] https://blog.csdn.net/weixin_40928253/article/details/80787158

代码实现链表的操作函数

1.首先是尾插 ,要实现尾插,首先的先有一个链表,并且为空。

即先构造一个链表,并且进行初始化。

//构造链表
typedef int DataType;
typedef struct SListNode {
DataType data;
struct SListNode *pNext;
} SListNode;
// 初始化
void SListInit(SListNode **ppFirst)
{
assert(ppFirst != NULL);
*ppFirst = NULL;
}
进行尾插前,我们的在构造一个新链表,用来存放尾插后形成的新链表。
SListNode * CreateNewNode(int data)
{
 SListNode *pNewNode = (SListNode *)malloc(sizeof(SListNode));
 assert(pNewNode);
 pNewNode->data = data;
 pNewNode->pNext = NULL;
 return pNewNode;
}
下面进行尾插
void PushBack(SListNode **ppFirst, DataType data)
{
 assert(ppFirst != NULL);
 SListNode *pNewNode = CreateNewNode(data);
 if (*ppFirst == NULL) {
  *ppFirst = pNewNode;
  return;
 }
 SListNode *pNode;
 pNode = *ppFirst;
 while (pNode->pNext != NULL) {
  pNode = pNode->pNext;
 }
 // pNode 就是倒数第一个
 pNode->pNext = pNewNode;
}
再加上打印函数与测试函数,main函数。
//print
void Print(SListNode *pFirst)
{
 SListNode *pNode;
 for (pNode = pFirst; pNode; pNode = pNode->pNext) {
  printf("%d -> ", pNode->data);
 }
 printf("NULL\n");
}
//测试函数
void TestSList()
{
 SListNode *pFirst;
 SListInit(&pFirst);
 assert(pFirst == NULL);
 PushBack(&pFirst, 1);
 assert(pFirst != NULL);
 Print(pFirst);
 PushBack(&pFirst, 2);
 PushBack(&pFirst, 3);
 PushBack(&pFirst, 4);
 Print(pFirst);
}
//main函数
#include"SList.h"
int main(){
 TestSList();
 system("pause");
}
效果如下

2.头插

void PushFront(SListNode **ppFirst, DataType data)

{assert(ppFirst != NULL);

SListNode *pNewNode = CreateNewNode(data);

pNewNode->pNext = *ppFirst;
*ppFirst = pNewNode;
}
测试函数如下:
PushFront(&pFirst, 5);
	PushFront(&pFirst, 8);
	Print(pFirst);

3.按下标插入(令给定下标是pos,pos一定存在)

void Insert(SListNode **ppFirst, SListNode *pPos, DataType data)
{
assert(ppFirst != NULL);
SListNode *pNode;
pNode = *ppFirst;
// pPos 是第一个结点地址
if (pPos == *ppFirst) {
PushFront(ppFirst, data);
return;
}
while (pNode->pNext != pPos){
pNode = pNode->pNext;
}
SListNode *pNewNode = CreateNewNode(data);
pNode->pNext = pNewNode;
pNewNode->pNext = pPos;
}
进行按给定位置插入 需确定pos位置,需定义find函数
//find
SListNode * Find(SListNode *pFirst, DataType data)
{
	SListNode *pNode;
for (pNode = pFirst; pNode; pNode = pNode->pNext) {
		if (pNode->data == data) {
			return pNode;
		}
	}
return NULL;
}
测试代码如下:
SListNode *pFound = Find(pFirst, 3);
	if (pFound == NULL) {
	printf("没有找到\n");
	}
	else {
	printf("%d\n", pFound->data);
	Insert(&pFirst, pFound, 100);
	}
Print(pFirst);
效果如下:

二、删除

1.头删

void PopFront(SListNode **ppFirst)
{
assert(ppFirst != NULL);
assert(*ppFirst != NULL);

SListNode *pOldFirst = *ppFirst;
*ppFirst = (*ppFirst)->pNext;
free(pOldFirst);
}
测试代码如下:
PopFront(&pFirst);
	Print(pFirst);
效果如下:

2.尾删

void PopBack(SListNode **ppFirst)
{
assert(ppFirst != NULL);
assert(*ppFirst != NULL);
if ((*ppFirst)->pNext == NULL) {
free(*ppFirst);
*ppFirst = NULL;
return;
}
SListNode *pNode = *ppFirst;
while (pNode->pNext->pNext != NULL)
{
pNode = pNode->pNext;
}
free(pNode->pNext);
pNode->pNext = NULL;
}
测试函数如下:
PopBack(&pFirst);
	Print(pFirst);
效果如下:

3.按位置删除(根据结点地址删除,结点肯定在链表里,令节点位置为pPos)

void Erase(SListNode **ppFirst, SListNode *pPos)
{
assert(ppFirst != NULL);
assert(*ppFirst != NULL);
if (*ppFirst == pPos) {
PopFront(ppFirst);
return;
}
SListNode *pCur;
for (pCur = *ppFirst; pCur->pNext != pPos; pCur = pCur->pNext) {
}
// pCur 就是 pPos的前一个
pCur->pNext = pPos->pNext;
free(pPos);
}
测试函数如下:
SListNode *pFound = Find(pFirst, 1);
	{	if (pFound == NULL) {
		printf("没有找到\n");
	}
	else {
		printf("%d\n", pFound->data);
		Erase(&pFirst, pFound);
	}
	SListDestroy(&pFirst);
	}
运行效果如下

4.按值删除(根据数据去删除,删除遇到的第一个结点)

void Remove(SListNode **ppFirst, DataType data)
{
SListNode *pFound = Find(*ppFirst, data);
if (pFound != NULL) {
Erase(ppFirst, pFound);
}
}
测试函数如下:
void TestRemove()
{
	SListNode *pFirst;
	SListInit(&pFirst);
PushBack(&pFirst, 4);
PushBack(&pFirst, 3);
PushBack(&pFirst, 1);
PushBack(&pFirst, 3);
PushBack(&pFirst, 3);
PushBack(&pFirst, 3);
PushBack(&pFirst, 3);
PushBack(&pFirst, 3);
PushBack(&pFirst, 5);
PushBack(&pFirst, 3);
Print(pFirst);
Remove(&pFirst, 3);
Print(pFirst);
运行效果如图

5.按值删除( 根据数据去删除,删除遇到的所有结点)

void RemoveAll(SListNode **ppFirst, DataType data)
{
SListNode *pNode = *ppFirst;
SListNode *pNext;
while (pNode->pNext) {
if (pNode->pNext->data == data) {
pNext = pNode->pNext;
pNode->pNext = pNode->pNext->pNext;
free(pNext);
}
else {
pNode = pNode->pNext;
}
}
if ((*ppFirst)->data == data) {
PopFront(ppFirst);
}
}
测试函数如下:
RemoveAll(&pFirst, 3);
Print(pFirst);
测试效果如下

源代码如下:

Hello.h
#pragma once
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
typedef int DataType;
typedef struct SListNode {
	DataType	data;
	struct SListNode *pNext;
}	SListNode;
// 初始化
void SListInit(SListNode **ppFirst)
{
	assert(ppFirst != NULL);
	*ppFirst = NULL;
}
SListNode * CreateNewNode(int data)
{
	SListNode *pNewNode = (SListNode *)malloc(sizeof(SListNode));
	assert(pNewNode);
	pNewNode->data = data;
	pNewNode->pNext = NULL;

	return pNewNode;
}
//打印函数
void Print(SListNode *pFirst)
{
	SListNode *pNode;
	for (pNode = pFirst; pNode; pNode = pNode->pNext) {
		printf("%d -> ", pNode->data);
	}
	printf("NULL\n");
}
// 销毁
void SListDestroy(SListNode **ppFirst)
{
	assert(ppFirst != NULL);
	SListNode	*pNode, *pNext;

	pNode = *ppFirst;
	while (pNode != NULL) {
		pNext = pNode->pNext;
		free(pNode);
		pNode = pNext;
	}
	*ppFirst = NULL;
}

// 查找,返回遇到的第一个
// 如果找到了,返回结点地址
// 否则返回 NULL
SListNode * Find(SListNode *pFirst, DataType data)
{
	SListNode *pNode;
	for (pNode = pFirst; pNode; pNode = pNode->pNext) {
		if (pNode->data == data) {
			return pNode;
		}
	}
    return NULL;
}
// 增删改查

// 尾插
void PushBack(SListNode **ppFirst, DataType data)
{
	assert(ppFirst != NULL);
SListNode *pNewNode = CreateNewNode(data);
	if (*ppFirst == NULL) {
		*ppFirst = pNewNode;
		return;
	}
	SListNode *pNode;
	pNode = *ppFirst;
	while (pNode->pNext != NULL) {
		pNode = pNode->pNext;
	}
	// pNode 就是倒数第一个
	pNode->pNext = pNewNode;
}
/*
// 头插
void PushFront(SListNode **ppFirst, DataType data)
{
assert(ppFirst != NULL);
SListNode *pNewNode = CreateNewNode(data);
pNewNode->pNext = *ppFirst;
*ppFirst = pNewNode;
}
// 插入到给定结点 pPos 前,pPos 肯定在链表里
void Insert(SListNode **ppFirst, SListNode *pPos, DataType data)
{
assert(ppFirst != NULL);
SListNode *pNode;
pNode = *ppFirst;
// pPos 是第一个结点地址
if (pPos == *ppFirst) {
PushFront(ppFirst, data);
return;
}
while (pNode->pNext != pPos){
pNode = pNode->pNext;
}
SListNode *pNewNode = CreateNewNode(data);
pNode->pNext = pNewNode;
pNewNode->pNext = pPos;
}
*/
// 头删
void PopFront(SListNode **ppFirst)
{
assert(ppFirst != NULL);
assert(*ppFirst != NULL);
SListNode *pOldFirst = *ppFirst;
*ppFirst = (*ppFirst)->pNext;
free(pOldFirst);
}
// 尾删
void PopBack(SListNode **ppFirst)
{
assert(ppFirst != NULL);
assert(*ppFirst != NULL);
if ((*ppFirst)->pNext == NULL) {
free(*ppFirst);
*ppFirst = NULL;
return;
}
SListNode *pNode = *ppFirst;
while (pNode->pNext->pNext != NULL)
{
pNode = pNode->pNext;
}
free(pNode->pNext);
pNode->pNext = NULL;
}
// 根据结点地址删除,结点肯定在链表里
void Erase(SListNode **ppFirst, SListNode *pPos)
{
assert(ppFirst != NULL);
assert(*ppFirst != NULL);
if (*ppFirst == pPos) {
PopFront(ppFirst);
return;
}
SListNode *pCur;
for (pCur = *ppFirst; pCur->pNext != pPos; pCur = pCur->pNext) {
}
// pCur 就是 pPos的前一个
pCur->pNext = pPos->pNext;
free(pPos);
}
/*
void TestSList()
{
	SListNode *pFirst;
	SListInit(&pFirst);
	assert(pFirst == NULL);
	PushBack(&pFirst, 1);
	assert(pFirst != NULL);
	Print(pFirst);
	PushBack(&pFirst, 1);
	PushBack(&pFirst, 2);
	PushBack(&pFirst, 3);
	Print(pFirst);
	PushFront(&pFirst, 5);
	PushFront(&pFirst, 8);
	Print(pFirst);
   SListNode *pFound = Find(pFirst, 3);
	if (pFound == NULL) {
	printf("没有找到\n");
	}
	else {
	printf("%d\n", pFound->data);
	Insert(&pFirst, pFound, 100);
	}
	Print(pFirst);
	PopFront(&pFirst);
	Print(pFirst);
	PopBack(&pFirst);
	Print(pFirst);
	SListNode *pFound = Find(pFirst, 9);
	{	if (pFound == NULL) {
		printf("没有找到\n");
	}
	else {
		printf("%d\n", pFound->data);
		Erase(&pFirst, pFound);
	}
	SListDestroy(&pFirst);
	}
}
*/
// 根据数据去删除,删除遇到的第一个结点
void Remove(SListNode **ppFirst, DataType data)
{
SListNode *pFound = Find(*ppFirst, data);
if (pFound != NULL) {
Erase(ppFirst, pFound);
}
}
// 根据数据去删除,删除遇到的所有结点
void RemoveAll(SListNode **ppFirst, DataType data)
{
SListNode *pNode = *ppFirst;
SListNode *pNext;
while (pNode->pNext) {
if (pNode->pNext->data == data) {
pNext = pNode->pNext;
pNode->pNext = pNode->pNext->pNext;
free(pNext);
}
else {
pNode = pNode->pNext;
}
}
if ((*ppFirst)->data == data) {
PopFront(ppFirst);
}
}
void TestRemove()
{
	SListNode *pFirst;
SListInit(&pFirst);
PushBack(&pFirst, 4);
PushBack(&pFirst, 3);
PushBack(&pFirst, 1);
PushBack(&pFirst, 3);
PushBack(&pFirst, 3);
PushBack(&pFirst, 3);
PushBack(&pFirst, 3);
PushBack(&pFirst, 3);
PushBack(&pFirst, 5);
PushBack(&pFirst, 3);
Print(pFirst);
Remove(&pFirst, 3);
Print(pFirst);
RemoveAll(&pFirst, 3);
Print(pFirst);
}
main.c
#include"Hello.h"
int main(){
	TestRemove();
	//TestSList();
	system("pause");
}

到此,单链表的基本功能差不多都实现了。
 

猜你喜欢

转载自blog.csdn.net/weixin_40928253/article/details/80787158