单链表函数功能实现

#pragma once
#include<assert.h>
#include<stdio.h>
#include<malloc.h>
typedef int SDataType;

typedef struct SlistNode
{
	SDataType data;
	struct SlistNode* pNext;
}Node;

typedef struct Slist
{
	Node* _head;
}Slist;

void SlistInit(Slist* pl)//初始化
{
	assert(pl);
	pl->_head = NULL;
}
Node* CreatSlistNode(SDataType data) //创建新节点
{
	Node* NewNode = (Node*)malloc(sizeof(Node));
	if (NewNode == NULL)
	{
		assert(0);
		return;
	}
	NewNode->data = data;
	NewNode->pNext = NULL;
	return NewNode;
}
void SlistPushBack(Slist* pl, SDataType data)//尾插
{
	Node* NewNode = NULL;
	Node* pur = NULL;
	assert(pl);
	NewNode = CreatSlistNode(data);
	pur = pl->_head;
	if (pl->_head == NULL)
	{
		pl->_head = NewNode;
	}
	else
	{
		while (pur->pNext)
		{
			pur = pur->pNext;
		}
		pur->pNext = NewNode;
	}
}
void SlistPushFront(Slist* pl, SDataType data)//头插
{
	Node* NewNode = NULL;
	NewNode = CreatSlistNode(data);
	assert(pl);
	NewNode->pNext = pl->_head;
	pl->_head = NewNode;
}
void SlistDelBack(Slist* pl)//尾删
{
	Node* pur;
	assert(pl);
	pur = pl->_head;
	if (pl->_head == NULL)
	{
		printf("无元素可删");
		return;
	}
	else if (pur->pNext == NULL)
	{
		free(pur);
		pl->_head = NULL;
	}
	else
	{
		while (pur->pNext->pNext)
		{
			pur = pur->pNext;
		}
		free(pur->pNext);//先释放空间
		pur->pNext = NULL;//再将野指针置空
	}

}
void SlistDelFront(Slist* pl)//头删
{
	if (pl->_head == NULL)
	{
		printf("无元素可删除");
	}
	else
	{
		Node* Temp = pl->_head->pNext;
		free(pl->_head);
		pl->_head = Temp;
	}
}
Node* SListFind(Slist* pl, SDataType x)//查找某个x的位置
{
	Node* cur = pl->_head;
	if (pl->_head == NULL)
		return;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		else
		{
			cur = cur->pNext;
		}
	}
	return NULL;
}
void SListInsertAfter(Node* pos, SDataType x) // 在pos的后面进行插入 
{
	Node* NewNode = CreatSlistNode(x);
	NewNode->pNext = pos->pNext;
	pos->pNext = NewNode;
}
void SListEraseAfter(Node* pos)//删除Pos后面的节点
{
	if (pos->pNext == NULL)
		return;
	else
	{
		Node* Temp = pos->pNext->pNext;
		free(pos->pNext);
		pos->pNext = Temp;
	}
}
void SlistPrint(Slist* pl)//打印
{
	Node* cur = pl->_head;
	while (cur)
	{
		printf("%d->", cur->data);
		cur = cur->pNext;
	}
	printf("NULL\n");
}
int SListEmpty(Slist* pl)//检查空
{
	return pl->_head == NULL;//为空返回1
}
int SListSize(Slist* pl)//判断长
{
	int count = 0;
	if (pl->_head == NULL)
		return 0;
	else
	{
		Node* cur = pl->_head;
		while (cur)
		{
			count++;
			cur = cur->pNext;
		}
		return count;
	}
}
void SListRemove(Slist* pl, SDataType x)//删除x
{
	if (pl->_head == NULL)
		return;
	else
	{
		Node* PreNode;
		Node* cur = pl->_head;
		if (pl->_head->data == x)
		{
			Node* temp = pl->_head->pNext;
			free(pl->_head);
			pl->_head = temp;
			return;
		}
		while (cur!=NULL)
		{
			if (cur->data == x)
			{
				Node* temp = cur->pNext;
				free(cur);
				PreNode->pNext = temp;
				return;
			}
			PreNode = cur;
			cur = cur->pNext;
		}
		return;
	}

}
void SListRemoveAll(Slist* pl, SDataType x)//删除所有x
{
	if (pl->_head == NULL)
		return;
	else
	{
		while(pl->_head->data == x)
		{
			Node* temp = pl->_head->pNext;
			free(pl->_head);
			pl->_head = temp;
		}
		Node* PreNode;
		Node* cur = pl->_head->pNext;
		while (cur != NULL)
		{
			while (cur != NULL&&cur->data == x)//先判断是否为空
			{
				Node* temp = cur->pNext;
				free(cur);
				PreNode->pNext = temp;
				cur = temp;
			}
			if (cur == NULL)
				return;
			PreNode = cur;
			cur = cur->pNext;
		}
		return;
	}

}

谈一下对删除特定节点,和删除所有特定节点函数的理解。
对于删除第一个特定元素函数,有三种情况。

  1. 判断链表是否为空
  2. 判断是否是头一个节点
  3. 再去判断是否是后面的节点
    这三种情况分先后,若出现其中一种情况,后面的就不再判断。

对于删除所有指定元素函数,同样的也要考虑这三种情况,不过还要注意的是当free掉当前节点后,必须重新给当前节点变量赋值,否则会导致出现野指针的现象,例如

			while (cur != NULL&&cur->data == x)//先判断是否为空
			{
				Node* temp = cur->pNext;
				free(cur);
				PreNode->pNext = temp;
				cur = temp;
			}

在这个里面每次free(cur)执行完,必须要重新给cur赋新值,否则他就会变成野指针。

发布了35 篇原创文章 · 获赞 13 · 访问量 2113

猜你喜欢

转载自blog.csdn.net/weixin_42458272/article/details/94347217