单链基本操作的部分思维导图
代码
头文件.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int DataType;
typedef struct ListNode{
struct ListNode *_pNext;
DataType _data;
}Node,*PNode;
void ListNodeInit(PNode* PHead); //初始化单链表
PNode BuyNode(DataType data); //创建新节点
void ListPushBack(PNode* PHead, DataType data); //尾插
void ListPopBack(PNode* PHead); // 尾删
void ListPushFront(PNode* PHead, DataType data); //头插
void ListPopFront(PNode* PHead);//头删
PNode ListFind(PNode PHead, DataType data); // 在链表中查找值为data的元素,找到后返回值为data的结点
void ListInsert(PNode* pHead, PNode pos, DataType data); // 在pos位置插入值为data的结点
void ListErase(PNode* pHead, PNode pos); // 删除pos位置的结点
int ListEmpty(PNode pHead); //判断链表是否为空
int SListSize(PNode pHead); // 获取链表中值data的结点
void SListDestroy(PNode* pHead); // 销毁聊表
PNode FindNode(PNode PHead, int pos); //查找已经存在的链表内是否存在第pos位结点
void ListPrint(PNode PHead); //打印结点内容
功能模块
#include"Apr_14.h"
//初始化链表
void ListNodeInit(PNode* pHead)
{
assert(pHead);
*pHead = NULL;
}
//申请节点
PNode BuyNode(DataType data)
{
PNode NewNode = (PNode)malloc(sizeof(Node)); //sizeof(Node) 内部一定是结点的大小,而不是指针的大小
if (NULL == NewNode) //虽然几率很小,但是万一申请失败程序就会崩溃,所以记得加容错机制
{
assert(0);
return NULL;
}
NewNode->_data = data;
NewNode->_pNext = NULL;
return NewNode;
}
//尾插
void ListPushBack(PNode* PHead, DataType data)
{
assert(PHead); //PHead内存的链表的地址,如果为空,则说明链表不存在
if (NULL == *PHead) //检查链表是否为空
*PHead = BuyNode(data);
else
{
PNode pCur = *PHead;
//找出最后一个结点
//while(pCur)也是寻找最后一个结点的一种方法,不过要保存它的前一个结点
while (pCur->_pNext)
{
pCur = pCur->_pNext;
}
pCur->_pNext = BuyNode(data);
}
}
//尾删
void ListPopBack(PNode* PHead)
{
PNode Del = NULL;
PNode prev = NULL;
assert(PHead);
if (NULL == *PHead) //链表为空,没有结点需要删除
{
return;
}
else if ((*PHead)->_pNext)
{
Del = *PHead;
while (Del->_pNext)
{
prev = Del;
Del = Del->_pNext;
}
free(Del);
prev->_pNext = NULL;
}
else if (*PHead)
{
free((*PHead));
*PHead = NULL;
}
}
//头插
void ListPushFront(PNode* PHead, DataType data)
{
assert(PHead);
PNode NewNode;
if (NULL == *PHead)
{
NewNode = BuyNode(data);
NewNode->_pNext = NULL;
*PHead = NewNode;
}
else
{
NewNode = BuyNode(data);
NewNode->_pNext = *PHead;
*PHead = NewNode;
}
}
//头删
void ListPopFront(PNode* PHead)
{
PNode Del = (*PHead);
PNode Pre = NULL;
assert(PHead);
if (NULL == PHead)
{
return;
}
if ((*PHead)->_pNext)
{
*PHead = (*PHead)->_pNext;
free(Del);
Del = NULL;
}
else if (*PHead)
{
free(Del);
*PHead = NULL;
}
}
// 在链表中查找值为data的元素,找到后返回值为data的结点
PNode ListFind(PNode PHead, DataType data)
{
PNode PCur = NULL;
assert(PHead);
if (NULL == PHead)
return NULL;
PCur = PHead;
while (PCur)
{
if (PCur->_data == data)
{
return PCur;
}
PCur = PCur->_pNext;
}
return NULL;
}
// 在pos位置插入值为data的结点
void ListInsert(PNode* PHead, PNode pos, DataType data)
{
assert(PHead);
if (NULL == (*PHead)) // 链表为空,自动头插
ListPushFront(PHead, data);
if (pos == NULL) //插入位置为空,缺省为头插
ListPushFront(PHead, data);
else if (!pos->_pNext) //插入位置为链表末尾
{
ListPushBack(PHead, data);
}
else
{
PNode PCur = NULL;
PNode NewNode = NULL;
DataType tmp;
NewNode = BuyNode(data);
NewNode->_pNext = pos->_pNext;
pos->_pNext = NewNode;
tmp = pos->_data;
pos->_data = data;
NewNode->_data = tmp;
}
}
// 删除pos位置的结点
void ListErase(PNode* PHead, PNode pos)
{
PNode Del = NULL;
PNode PPre = NULL;
assert(PHead);
if (NULL == *PHead || NULL == pos)
return;
Del = *PHead;
while (Del && Del != pos)
{
PPre = Del;
Del = Del->_pNext;
}
if (Del->_pNext != NULL)
{
PPre->_pNext = Del->_pNext;
free(Del);
Del = NULL;
}
else
{
free(Del);
PPre->_pNext = NULL;
}
}
int ListEmpty(PNode pHead)
{
if (NULL == pHead)
{
printf("链表为空\n");
return 0;
}
else
{
return 1;
}
}
// 销毁链表
void SListDestroy(PNode* PHead)
{
PNode Des;
assert(PHead);
if (NULL == (PHead))
return;
Des = *PHead;
while (Des)
{
Des = (*PHead)->_pNext;
free(*PHead);
if (Des)
(*PHead) = Des;
}
*PHead = NULL;
}
//查找链表中是否存在第pos个结点
PNode FindNode(PNode PHead, int pos)
{
PNode PCur = NULL;
PNode PPre = NULL;
if (NULL == PHead)
{
return NULL;
}
PCur = PHead;
while (pos && PCur)
{
PPre = PCur;
PCur = PCur->_pNext;
pos--;
}
if (pos == 0)
return PPre;
else
return NULL;
}
//打印
void ListPrint(PNode PHead)
{
if (NULL == PHead)
return;
while (PHead)
{
printf("%d ", PHead->_data);
PHead = PHead->_pNext;
}
printf("\n");
}
测试文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"Apr_14.h"
void TestPushOrPop()
{
PNode PHead;
ListNodeInit(&PHead);
ListPushBack(&PHead, 6);
ListPushBack(&PHead, 9);
ListPushBack(&PHead, 8);
ListPrint(PHead);
ListPopBack(&PHead);
ListPushBack(&PHead, 11);
ListPrint(PHead);
ListPopBack(&PHead);
ListPushFront(&PHead, 3);
ListPrint(PHead);
ListPopFront(&PHead);
ListPrint(PHead);
}
void TestListFind()
{
PNode PHead;
PNode tmp = NULL;
ListNodeInit(&PHead);
ListPushBack(&PHead, 6);
ListPrint(PHead);
ListPushBack(&PHead, 9);
ListPushBack(&PHead, 8);
ListPushFront(&PHead, 3);
ListPushFront(&PHead, 7);
ListPushFront(&PHead, 1);
ListPrint(PHead);
tmp = ListFind(PHead, 9);
if (tmp)
{
printf("%d\n", tmp->_data);
}
tmp = FindNode(PHead, 3);
if (tmp)
{
printf("%d\n", tmp->_data);
}
ListInsert(&PHead, tmp, 13);
ListPrint(PHead);
tmp = NULL;
ListInsert(&PHead, tmp, 0);
ListPrint(PHead);
tmp = FindNode(PHead, 6);
ListErase(&PHead, tmp);
ListPrint(PHead);
tmp = FindNode(PHead, 7);
ListErase(&PHead, tmp);
ListPrint(PHead);
SListDestroy(&PHead);
}
int main()
{
TestPushOrPop();
TestListFind();
system("pause");
return 0;
}