#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;
}
}
谈一下对删除特定节点,和删除所有特定节点函数的理解。
对于删除第一个特定元素函数,有三种情况。
- 判断链表是否为空
- 判断是否是头一个节点
- 再去判断是否是后面的节点
这三种情况分先后,若出现其中一种情况,后面的就不再判断。
对于删除所有指定元素函数,同样的也要考虑这三种情况,不过还要注意的是当free掉当前节点后,必须重新给当前节点变量赋值,否则会导致出现野指针的现象,例如
while (cur != NULL&&cur->data == x)//先判断是否为空
{
Node* temp = cur->pNext;
free(cur);
PreNode->pNext = temp;
cur = temp;
}
在这个里面每次free(cur)执行完,必须要重新给cur赋新值,否则他就会变成野指针。