链表中的数据是以结点来表示的。
每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置)。
typedef int DataType;//用typedef定义int类型的别名叫DataType
typedef struct SListNode {
DataType data; // 值
struct SListNode *pNext; // 指向下一个结点
} SListNode;
// 初始化
void SListInit(SListNode **ppFirst)
{
//初始化则把头节点置空即可,申请空间会在需要时写出
*ppFirst = NULL;
}
static SListNode * BuyNewNode(DataType data)
{
SListNode *pNewNode = (SListNode *)malloc(sizeof(SListNode));
assert(pNewNode);
pNewNode->data = data;
pNewNode->pNext = NULL;
return pNewNode;
}
void SListPushFront(SListNode **ppFirst, DataType data)
{
SListNode *newNode = BuyNewNode(data);//插入前肯定要买一个节点了
newNode->pNext = *ppFirst;
*ppFirst = newNode;
}
void SListPushBack(SListNode** ppFirst, DataType data)
{
//尾插肯定要买一个节点
SListNode *newNode = BuyNewNode(data);
//如果链表是空的,就把新节点给*ppfirst
if (*ppFirst == NULL)
{
*ppFirst = newNode;
return;
}
SListNode *pNode = *ppFirst;
for (pNode; pNode->pNext != NULL; pNode = pNode->pNext)
{
;
}
//到这里,找到了最后一个节点
newNode->pNext = pNode->pNext;//将新节点的next指向原来pnode的next,(即null)
pNode->pNext = newNode;//然后让原来节点的next指向新节点
}
void SListPopFront(SListNode **ppFirst)
{
if (*ppFirst == NULL)
{
printf("链表是空的");
return;
}
//把第一个节点phead初始化设置好
SListNode *pHead = *ppFirst;
//*pnext是第二个节点
SListNode *pNext = pHead->pNext;
//释放头节点
free(pHead);
//将第二个节点置成ppfirst(头节点)
*ppFirst = pNext;
}
void SListPopBack(SListNode **ppFirst)
{
//排除链表为空的情况
if (*ppFirst == NULL)
{
printf("链表为空\n");
return;
}
//如果链表里就只有一个元素,直接删除
if ((*ppFirst)->pNext == NULL)
{
free(*ppFirst);
*ppFirst = NULL;
}
SListNode *pNode, *pNext;
pNode = *ppFirst;
//找到倒数第二个元素,
while (pNode->pNext->pNext != NULL)
{
pNode = pNode->pNext;
}
pNext = pNode->pNext;//设置为pnode的下一个节点为pnext(即找到最后一个节点)
pNode->pNext = pNext->pNext;//把pnode的next直接指向null
free(pNext);//释放最后一个节点
}
void SListInsert(SListNode **ppFirst, SListNode *pPos, DataType data)
{
//如果链表是空的,则可以直接头插
if (*ppFirst == NULL && pPos == NULL)
{
SListPushFront(ppFirst, data);
return;
}
SListNode *pNode;
//找到ppos
for (pNode = *ppFirst; pNode->pNext != pPos; pNode = pNode->pNext)
{
;
}
//买一个节点
SListNode* pNewNode = BuyNewNode(data);
//将新节点的pnext指向ppos
pNewNode->pNext = pPos;
//将ppos的前一个节点pnode 的 pnext 指向新节点
pNode->pNext = pNewNode;
}
void SListErase(SListNode **ppFirst, SListNode *pPos)
{
//如果给定的节点就是当前第一个节点,直接头删
if (*ppFirst == pPos)
{
SListPopFront(ppFirst);
return;
}
SListNode* pNode;
//找到ppos
for (pNode = *ppFirst; pNode->pNext != pPos; pNode = pNode->pNext)
{
;
}
//pnode是ppos的前一个节点
//将pnode的next指向ppos的下一个节点
pNode->pNext = pPos->pNext;
//释放ppos即可
free(pPos);
}
SListNode* SListFind(SListNode *pFirst, DataType data)
{
SListNode* pNode;
pNode = pFirst;
while (pNode != NULL)
{
if (pNode->data == data)
{
printf("找到了%d\n",pNode->data);
return pNode;
}
pNode = pNode->pNext;
}
printf("链表中没有此值:%d\n",data);
return NULL;
}
void SListRemove(SListNode **ppFirst, DataType data)
{
if (*ppFirst == NULL)
{
printf("链表为空\n");
return;
}
//按值删除的话,肯定要先按值找到哪个节点,slistfind返回的是那个节点的地址
SListNode* res = SListFind(*ppFirst, data);
//如果找到了那第一个符合的节点,就删除给定节点
if (res != NULL)
{
printf("开始删除\n", data);
SListErase(ppFirst, res);//按给定节点进行删除
return;
}
printf("链表中没有这个值\n");
}
void SListRemoveAll(SListNode **ppFirst, DataType data)
{
if (*ppFirst == NULL)
{
printf("链表为空\n");
return;
}
SListNode* pNode = *ppFirst;
SListNode* pDel;//这里要保存删除节点的信息,防止直接删除后信息丢失
printf("开始删除链表中所有此值:%d\n", data);
while (pNode->pNext != NULL)//按值删除,遍历链表里所有的节点
{
//删除时,不能直接定位到目标节点,否则会丢失信息,应该要先保存起来
if (pNode->pNext->data == data)
{
pDel = pNode->pNext;
pNode->pNext = pDel->pNext;
free(pDel);
}
else
{
pNode = pNode->pNext;
}
//别忘记考虑第一个节点
if ((*ppFirst)->data == data)
{
//如果是第一个节点,那就直接头删掉即可
SListPopFront(ppFirst);
}
}
}
void SListDestroy(SListNode **ppFirst)
{
SListNode *pNode, *pNext;
for (pNode = *ppFirst; pNode != NULL; pNode = pNext)
{
pNext = pNode->pNext;
free(pNode);
}
*ppFirst = NULL;
}
void Print(SListNode *pHead)
{
SListNode *pNode;
for (pNode = pHead; pNode != NULL; pNode = pNode->pNext)
{
printf("%2d-> ", pNode->data);
}
printf("NULL\n");
}
void test()
{
SListNode *SList;
SListInit(&SList);
SListPushBack(&SList, 3);
SListPushFront(&SList, 1);
SListPushBack(&SList, 3);
SListPushFront(&SList, 2);
SListPushFront(&SList, 3);
SListPushBack(&SList, 3);
SListPushBack(&SList, 3);
SListPushBack(&SList, 4);
SListPushBack(&SList, 3);
Print(SList);
//SListPopBack(&SList);
//SListPopFront(&SList);
SListFind(SList, 5);
SListRemove(&SList, 2);
SListRemoveAll(&SList, 3);
Print(SList);
}
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include"lb.h"
int main()
{
test();
system("pause");
return 0;
}