#include "SList.h"
#include "malloc.h"
#include "assert.h"
#include <stdio.h>
void SListInit(SList* s)//初始化
{
assert(s);//链表存在
s->_pHead = NULL;//暂时还没有节点,所以置空
}
PNode BuySListNode(SDataType data)//买节点,申请空间,放数据
{
PNode pNewNode = (PNode)malloc(sizeof(Node));//此时应该是一个结构体类型。
//但malloc返回的是一个void*
//(PNode)强制类型转换
if (NULL == pNewNode)//申请失败
{
assert(0);
return 0;
}
pNewNode->_data = data;//申请空间成功,放数据
pNewNode->_pNext = NULL;//不知道下一个数据是否有,所以置空
return pNewNode;
}
void PrintSList(SList* s)//打印链表
{
assert(s);
PNode pCur = s->_pHead;
while (pCur)
{
printf("%d----", pCur->_data);
pCur = pCur->_pNext;//让pCur往后走
}
printf("NULL\n");
}
//下面的操作是以不带头结点为例
void SListPushBack(SList* s, SDataType data)//尾插
{
assert(s);
PNode pNewNode = BuySListNode(data);
if (NULL == s->_pHead)//链表为空,即无节点
{
s->_pHead = pNewNode;
}
else//链表不为空
{
PNode pCur = s->_pHead;
}
while (pCur->_pNext)//判断后面还有节点
{
pCur = pCur->_pNext;//一直往后走,找到最后一个节点
pCur->_pNext = pNewNode;//让最后一个节点指向新节点
}
}
void SListPopBack(SList* s)//尾删
{
if (NULL == s->_pHead)//为空
{
return;
}
else if (NULL == s->_pHead->_pNext)//判断是否只有一个节点
// (即头节点就是第一个节点)
{
free(s->_pHead);//头节点指向的是第一个节点,释放的就是第一个节点
s->_pHead = NULL;
}
else//有多个节点
{
PNode pPre = NULL;//刚开始cur 在第一个,是没有pre
PNode pCur = s->_pHead;//cur从head开始往后找最后一个节点
while (pCur_ > _Next)
{
pPre = pCur;//记录pre(保存cur前一个数据),便于后面next域指向空
pCur = pCur->_pNext;//往后走
}
free(pCur);//释放cur空间,让前一个数据pPre指向NULL
pPre->_pNext = NULL;//pre中next域指向空,
//不可直接用cur指向空,它只是一个临时空间
}
void SListPushFront(SList* s, SDataType data)//头插
{
assert(s);
PNode pNewNode = BuySListNode(data);
pNewNode->_pNext = s->_pHead;//先用新节点的next域把第一个节点保存起来
s->_pHead = pNewNode;
}
void SListPopFront(SList* s)//头删
{
pNode pDelNode == NULL;//声明pDelNode,便于后面使用,C语言的缺陷
assert(s);
if (NULL == s->_pHead)
return;
pDelNode = s->_pHead;//找到待删除的节点即head指向的位置节点
s->_pHead = pDelNode->_pNext;//删完后指向
free(pDelNode);
}
void SListInsert(PNode pos, SDataType data)//任意位置的插入
{
PNode pNewNode = NULL;//先声明后使用
if (NULL == pos)
return;
pNewNode = BuySListNode(data);
pNewNode->_pNext = pos->_pNext;//先不要破坏原链表结构,
// 先用新节点的next指针域指向pos的下一个,然后再断开原链表
pos->_pNext = PNewNode;//pos的下一个指向新节点,即之前链表断开了
}
void SListErase(SList* s, PNode pos)//任意位置的删除
{
assert(s);
if (NULL == pos || NULL == s->_pHead)//判断是否为空链表
return;
if (pos == s->_pHead)//pos在第一个节点的位置
{
s->_pHead = pos->_pNext;
free(pos);
}
else
{
PNode pPrePos = s->_pHead;//因为用pre从head开始找pos
//当链表是1--2---3---4--NULL pos在3的位置,当pre是1时,
//因为pos是3时,prepos按道理是2,但现在在1位置
//就开始运行程序了,即此时prepos=NULL,所以程序会崩溃
//所以判断prepos是否为空
while (pPrepos && pPrePos->_pNext != pos)//判断pPrepos不为空并且next!=pos
{
prePos = prePos->_pNext;//往后走。继续找
if(pPrePos)//判断prepos不为空
pPrePos->_pNext = pos->_pNext;
free(pos);
}
}
PNode SListFind(SList* s, SDataType data)//找到pos位置删除或插入
{
assert(s);
PNode pCur = s->_pHead;
while (pCur)
{
if (pCur->_data == data)
{
return pCur;//找到了
}
pCur = pCur->_pNext;
}
return NULL;
}
int SListSize(SList* s)
{
assert(s);
PNode pCur = s->_pHead;
size_t count = 0;
while (pCur)
{
count++;
pCur = pCur->_pNext;
}
return count;
}
int SListEmpty(SList* s)
{
assert(s);//不是空链表
return NULL = s->_pHead;//如果是空
}
void SListRmove(SList* s, SDataType data)
{
assert(s);
PNode pCur = s->_pHead;
if (NULL == s->pHead)
return;
while (pCur)
{
if (pCur->_data == data)//判断找到的数是否是data
{
if (pCur = s->pHead)//data在第一个节点
s->_pHead = pCur->_pNext;
free(pCur);
}
}
else//data不在第一个节点
{
pCur->_pPre = NULL;
pPre_>_pNext = pCur->_pNext;
free(pCur);
}
void SListRmoveAll(SList* s, SDataType data)//------有图片D理解
{
assert(s);
PNode pCur = s->_pHead;
if (NULL == s->pHead)
return;
while (pCur)
{
if (pCur->_data == data)
{
if (NULL == pPre)
{
s->pHead = pCur->_pNext;
free(pCur);
pCur = s->pHead;
}
else//非第一个节点
{
pPre->pNext = pCur->_pNext;
free(pCur);
pCur = pPre->_pNext;
}
}
else//如果不是data数据,则往后走一步。得先把前一个保存起来
{
pPre = pCur;
pCur = pCur->_pNext;//则往后走
}
}
return s->pHead;//完成所有操作后记得返回链表
}
单向不带头结点链表一些常见操作
最新推荐文章于 2022-07-02 23:30:15 发布