#pragma once
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>
typedef int DataType;
typedef struct SListNode{
DataType data;
struct SListNode *pNext;
}SListNode;
//初始化
void SListInit(SListNode **ppfirst){
assert(ppfirst);
*ppfirst = NULL;
}
//销毁
void Slistdestroy(SListNode **ppfirst){
assert(ppfirst);
SListNode *pNode, *pNext;
pNode = *ppfirst;
while (pNode != NULL);
{
pNext = pNode->pNext;
free(pNode);
pNode = pNext;
}
*ppfirst = NULL;
}
//销毁
void SListDestroy(SListNode **ppfirst)
{
assert(ppfirst != NULL);
SListNode *pNode, *pNext;
pNode = *ppfirst;
while (pNode != NULL)
{
pNext = pNode->pNext;
free(pNode);
pNode = pNext;
}
*ppfirst = NULL;
}
//增删改查
SListNode *CreatNewNode(int data)
{
SListNode *pNewNode = (SListNode*)malloc(sizeof(SListNode));
assert(pNewNode);
pNewNode->data = data;
pNewNode->pNext = NULL;
return pNewNode;
}
//尾插
void SListPushback(SListNode **ppfirst, DataType data){
assert(ppfirst);
SListNode *pNewNode = CreatNewNode(data);
if (*ppfirst == NULL)
{
*ppfirst = pNewNode;
return;
}
SListNode *pNode;
pNode = *ppfirst;
while (pNode->pNext != NULL)
{
pNode = pNode->pNext;
}
pNode->pNext = pNewNode;
}
//头插
void SListPushFront(SListNode **ppfirst,DataType data)
{
assert(ppfirst);
SListNode *pNewNode = CreatNewNode(data);
pNewNode->pNext = *ppfirst;
*ppfirst = pNewNode;
}
//插入到指定的节点pPos前,pPos肯定在节点里
void InSert(SListNode **ppfirst, SListNode *pPos, DataType data)
{
assert(ppfirst != NULL);
assert(pPos != NULL);
SListNode *pNode;
SListNode *pos = pPos;
if (pos == *ppfirst)
{
SListPushFront(ppfirst, data);
return;
}
SListNode *pNewNode = CreatNewNode(data);
for (pNode = *ppfirst; pNode->pNext != pos; pNode = pNode->pNext)
{
}
pNode->pNext = pNewNode;
pNewNode->pNext = pos;
}
//查找,返回遇到的第一个
//如果找到返回节点地址
//如果没找到,返回NULL
SListNode *Find(SListNode **ppfirst, DataType data){
assert(ppfirst);
SListNode *pNode;
for (pNode = *ppfirst; pNode; pNode = pNode->pNext)
{
if (pNode->data == data)
{
return pNode;
}
}
return NULL;
}
//打印
void print(SListNode *pfirst){
assert(pfirst);
SListNode *pNode = pfirst;
for (pNode = pfirst; pNode != NULL; pNode = pNode->pNext)
{
printf("%d ->", pNode->data);
}
printf("NULL \n");
}
void TestSList()
{
SListNode *pFirst = NULL;
//SListInit(&pFirst);
//SListPushback(&pFirst, 1);
//SListPushback(&pFirst, 2);
SListPushback(&pFirst, 3);
SListPushback(&pFirst, 4);
SListPushFront(&pFirst, 5);
SListPushFront(&pFirst, 6);
SListPushFront(&pFirst, 7);
print(pFirst);
SListNode *pFound = Find(&pFirst, 6);
if (pFound == NULL)
{
printf("没有找到\n");
}
else{
printf("%d\n", pFound->data);
InSert(&pFirst, pFound,100);
print(pFirst);
}
}
//头删
void PopFront(SListNode **ppfirst)
{
assert(ppfirst != NULL);
assert(*ppfirst != NULL);
SListNode *pNode = *ppfirst;
*ppfirst = pNode->pNext;
free(pNode);
}
//尾删
void PopBack(SListNode **ppfirst)
{
assert(ppfirst != NULL);
assert(*ppfirst != NULL);
SListNode *pfirst = *ppfirst;
if ((pfirst->pNext) == NULL)
{
free(pfirst);
pfirst = NULL;
return;
}
while (pfirst->pNext->pNext != NULL)
{
pfirst = pfirst->pNext;
}
free(pfirst->pNext);
pfirst->pNext = NULL;
}
//根据节点地址删除,节点肯定在链表里
void Erase(SListNode **ppfirst, SListNode *pPos)
{
assert(ppfirst != NULL);
assert(*ppfirst != NULL);
SListNode *pos = pPos;
SListNode *pfirst = *ppfirst;
if (pfirst == pos)
{
PopFront(ppfirst);
return;
}
while (pfirst->pNext != pos)
{
pfirst = pfirst->pNext;
}
pfirst->pNext = pos->pNext;
free(pos);
}
//根据数据去删除,删除遇到的第一个节点
void Remove(SListNode **ppfirst, DataType data)
{
SListNode *pNode = *ppfirst;
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 TextList()
{
SListNode *pFirst = NULL;
SListPushback(&pFirst, 3);
SListPushback(&pFirst, 5);
SListPushback(&pFirst, 6);
SListPushback(&pFirst, 8);
SListPushback(&pFirst, 8);
SListPushback(&pFirst, 8);
SListPushback(&pFirst, 8);
SListPushback(&pFirst, 5);
SListPushback(&pFirst, 0);
SListPushback(&pFirst, 3);
print(pFirst);
PopFront(&pFirst);
//PopFront(&pFirst);
//PopFront(&pFirst);
PopBack(&pFirst);
print(pFirst);
SListNode *pFound = Find(&pFirst, 5);
if (pFound == NULL)
{
printf("nothing");
}
else{
printf("%d\n", pFound->data);
Erase(&pFirst,pFound);
}
print(pFirst);
Remove(&pFirst, 5);
print(pFirst);
RemoveAll(&pFirst, 6);
print(pFirst);
SListDestroy(&pFirst);
}
定义一个结构体,这个结构体就是链表的结点,里面有两个参数,一个data是链表节点的数据,一个pNext,存放的是下一个节点的地址,最后一个节点的pNext指向NULL。
pFirst是链表的首节点的地址
程序中使用的增删改查函数的参数全部是二级指针 ,需要特别注意。
代码开始将节点数据类型重命名,这样若需要更改数据类型时更加方便。