链表
链表:一种链式存储的线性表,用一组地址任意的存储单元存放线性表的 数据元素,称存储单元为一个节点
头文件SList.h
#pragma once
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
typedef int DataType;
typedef struct SListNode {
DataType data;
struct SListNode *pNext;
} SListNode;
// 初始化
void SListInit(SListNode **ppFirst);
// 销毁
void SListDestroy(SListNode **ppFirst);
SListNode * CreateNewNode(int data);
// 尾插
void PushBack(SListNode **ppFirst, DataType data);
// 头插
void PushFront(SListNode **ppFirst, DataType data);
// 插入到给定结点 pPos 前,pPos 肯定在链表里
void Insert(SListNode **ppFirst, SListNode *pPos, DataType data);
// 根据数据去删除,删除遇到的第一个结点
void Remove(SListNode **ppFirst, DataType data);
// 根据数据去删除,删除遇到的所有结点
void RemoveAll(SListNode **ppFirst, DataType data);
//查找
SListNode * Find(SListNode *pFirst, DataType data);
// 打印
void Print(SListNode *pFirst);
源文件SList.c
#include "SList.h"
// 初始化
void SListInit(SListNode **ppFirst)
{
assert(ppFirst != NULL);
*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 * CreateNewNode(int data)
{
SListNode *pNewNode = (SListNode *)malloc(sizeof(SListNode));
assert(pNewNode);
pNewNode->data = data;
pNewNode->pNext = NULL;
return pNewNode;
}
// 尾插
void PushBack(SListNode **ppFirst, DataType data)
{
assert(ppFirst != NULL);
SListNode *pNewNode = CreateNewNode(data);
if (*ppFirst == NULL) {
*ppFirst = pNewNode;
return;
}
SListNode *pNode;
pNode = *ppFirst;
while (pNode->pNext != NULL) {
pNode = pNode->pNext;
}
// pNode 就是倒数第一个
pNode->pNext = pNewNode;
}
// 头插
void PushFront(SListNode **ppFirst, DataType data)
{
assert(ppFirst != NULL);
SListNode *pNewNode = CreateNewNode(data);
pNewNode->pNext = *ppFirst;
*ppFirst = pNewNode;
}
// 插入到给定结点 pPos 前,pPos 肯定在链表里
void Insert(SListNode **ppFirst, SListNode *pPos, DataType data)
{
assert(ppFirst != NULL);
SListNode *pNode;
pNode = *ppFirst;
// pPos 是第一个结点地址
if (pPos == *ppFirst) {
PushFront(ppFirst, data);
return;
}
while (pNode->pNext != pPos){
pNode = pNode->pNext;
}
SListNode *pNewNode = CreateNewNode(data);
pNode->pNext = pNewNode;
pNewNode->pNext = pPos;
}
void Print(SListNode *pFirst)
{
SListNode *pNode;
for (pNode = pFirst; pNode; pNode = pNode->pNext) {
printf("%d -> ", pNode->data);
}
printf("NULL\n");
}
// 头删
void PopFront(SListNode **ppFirst)
{
assert(ppFirst != NULL);
assert(*ppFirst != NULL);
SListNode *pOldFirst = *ppFirst;
*ppFirst = (*ppFirst)->pNext;
free(pOldFirst);
}
// 尾删
void PopBack(SListNode **ppFirst)
{
assert(ppFirst != NULL);
assert(*ppFirst != NULL);
if ((*ppFirst)->pNext == NULL) {
free(*ppFirst);
*ppFirst = NULL;
return;
}
SListNode *pNode = *ppFirst;
while (pNode->pNext->pNext != NULL)
{
pNode = pNode->pNext;
}
free(pNode->pNext);
pNode->pNext = NULL;
}
// 根据结点地址删除,结点肯定在链表里
void Erase(SListNode **ppFirst, SListNode *pPos)
{
assert(ppFirst != NULL);
assert(*ppFirst != NULL);
if (*ppFirst == pPos) {
PopFront(ppFirst);
return;
}
SListNode *pCur;
for (pCur = *ppFirst; pCur->pNext != pPos; pCur = pCur->pNext) {
}
// pCur 就是 pPos的前一个
pCur->pNext = pPos->pNext;
free(pPos);
}
// 查找,返回遇到的第一个
// 如果找到了,返回结点地址
// 否则返回 NULL
SListNode * Find(SListNode *pFirst, DataType data)
{
SListNode *pNode;
for (pNode = pFirst; pNode; pNode = pNode->pNext) {
if (pNode->data == data) {
return pNode;
}
}
return NULL;
}
// 根据数据去删除,删除遇到的第一个结点
void Remove(SListNode **ppFirst, DataType data)
{
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 TestRemove()
{
SListNode *pFirst;
SListInit(&pFirst);
PushBack(&pFirst, 3);
PushBack(&pFirst, 4);
PushBack(&pFirst, 3);
PushBack(&pFirst, 1);
PushBack(&pFirst, 3);
PushBack(&pFirst, 5);
PushBack(&pFirst, 3);
Print(pFirst);
RemoveAll(&pFirst, 3);
Print(pFirst);
}