版权声明:转载请联系 :[email protected] https://blog.csdn.net/weixin_40928253/article/details/80787158
代码实现链表的操作函数
1.首先是尾插 ,要实现尾插,首先的先有一个链表,并且为空。
即先构造一个链表,并且进行初始化。
//构造链表
typedef int DataType;
typedef struct SListNode {
DataType data;
struct SListNode *pNext;
} SListNode;
// 初始化
void SListInit(SListNode **ppFirst)
{
assert(ppFirst != NULL);
*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;
}
再加上打印函数与测试函数,main函数。
//print
void Print(SListNode *pFirst)
{
SListNode *pNode;
for (pNode = pFirst; pNode; pNode = pNode->pNext) {
printf("%d -> ", pNode->data);
}
printf("NULL\n");
}
//测试函数
void TestSList()
{
SListNode *pFirst;
SListInit(&pFirst);
assert(pFirst == NULL);
PushBack(&pFirst, 1);
assert(pFirst != NULL);
Print(pFirst);
PushBack(&pFirst, 2);
PushBack(&pFirst, 3);
PushBack(&pFirst, 4);
Print(pFirst);
}
//main函数
#include"SList.h"
int main(){
TestSList();
system("pause");
}
效果如下
2.头插
void PushFront(SListNode **ppFirst, DataType data)
{assert(ppFirst != NULL);
SListNode *pNewNode = CreateNewNode(data);
pNewNode->pNext = *ppFirst;
*ppFirst = pNewNode;
}
测试函数如下:
PushFront(&pFirst, 5);
PushFront(&pFirst, 8);
Print(pFirst);
3.按下标插入(令给定下标是pos,pos一定存在)
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;
}
进行按给定位置插入 需确定pos位置,需定义find函数
//find
SListNode * Find(SListNode *pFirst, DataType data)
{
SListNode *pNode;
for (pNode = pFirst; pNode; pNode = pNode->pNext) {
if (pNode->data == data) {
return pNode;
}
}
return NULL;
}
测试代码如下:
SListNode *pFound = Find(pFirst, 3);
if (pFound == NULL) {
printf("没有找到\n");
}
else {
printf("%d\n", pFound->data);
Insert(&pFirst, pFound, 100);
}
Print(pFirst);
效果如下:
二、删除
1.头删
void PopFront(SListNode **ppFirst)
{
assert(ppFirst != NULL);
assert(*ppFirst != NULL);
SListNode *pOldFirst = *ppFirst;
*ppFirst = (*ppFirst)->pNext;
free(pOldFirst);
}
测试代码如下:
PopFront(&pFirst);
Print(pFirst);
效果如下:
2.尾删
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;
}
测试函数如下:
PopBack(&pFirst);
Print(pFirst);
效果如下:
3.按位置删除(根据结点地址删除,结点肯定在链表里,令节点位置为pPos)
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);
}
测试函数如下:
SListNode *pFound = Find(pFirst, 1);
{ if (pFound == NULL) {
printf("没有找到\n");
}
else {
printf("%d\n", pFound->data);
Erase(&pFirst, pFound);
}
SListDestroy(&pFirst);
}
运行效果如下
4.按值删除(根据数据去删除,删除遇到的第一个结点)
void Remove(SListNode **ppFirst, DataType data)
{
SListNode *pFound = Find(*ppFirst, data);
if (pFound != NULL) {
Erase(ppFirst, pFound);
}
}
测试函数如下:
void TestRemove()
{
SListNode *pFirst;
SListInit(&pFirst);
PushBack(&pFirst, 4);
PushBack(&pFirst, 3);
PushBack(&pFirst, 1);
PushBack(&pFirst, 3);
PushBack(&pFirst, 3);
PushBack(&pFirst, 3);
PushBack(&pFirst, 3);
PushBack(&pFirst, 3);
PushBack(&pFirst, 5);
PushBack(&pFirst, 3);
Print(pFirst);
Remove(&pFirst, 3);
Print(pFirst);
运行效果如图
5.按值删除( 根据数据去删除,删除遇到的所有结点)
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);
}
}
测试函数如下:
RemoveAll(&pFirst, 3);
Print(pFirst);
测试效果如下
源代码如下:
Hello.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)
{
assert(ppFirst != NULL);
*ppFirst = NULL;
}
SListNode * CreateNewNode(int data)
{
SListNode *pNewNode = (SListNode *)malloc(sizeof(SListNode));
assert(pNewNode);
pNewNode->data = data;
pNewNode->pNext = NULL;
return pNewNode;
}
//打印函数
void Print(SListNode *pFirst)
{
SListNode *pNode;
for (pNode = pFirst; pNode; pNode = pNode->pNext) {
printf("%d -> ", pNode->data);
}
printf("NULL\n");
}
// 销毁
void SListDestroy(SListNode **ppFirst)
{
assert(ppFirst != NULL);
SListNode *pNode, *pNext;
pNode = *ppFirst;
while (pNode != NULL) {
pNext = pNode->pNext;
free(pNode);
pNode = pNext;
}
*ppFirst = NULL;
}
// 查找,返回遇到的第一个
// 如果找到了,返回结点地址
// 否则返回 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 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 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);
}
/*
void TestSList()
{
SListNode *pFirst;
SListInit(&pFirst);
assert(pFirst == NULL);
PushBack(&pFirst, 1);
assert(pFirst != NULL);
Print(pFirst);
PushBack(&pFirst, 1);
PushBack(&pFirst, 2);
PushBack(&pFirst, 3);
Print(pFirst);
PushFront(&pFirst, 5);
PushFront(&pFirst, 8);
Print(pFirst);
SListNode *pFound = Find(pFirst, 3);
if (pFound == NULL) {
printf("没有找到\n");
}
else {
printf("%d\n", pFound->data);
Insert(&pFirst, pFound, 100);
}
Print(pFirst);
PopFront(&pFirst);
Print(pFirst);
PopBack(&pFirst);
Print(pFirst);
SListNode *pFound = Find(pFirst, 9);
{ if (pFound == NULL) {
printf("没有找到\n");
}
else {
printf("%d\n", pFound->data);
Erase(&pFirst, pFound);
}
SListDestroy(&pFirst);
}
}
*/
// 根据数据去删除,删除遇到的第一个结点
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, 4);
PushBack(&pFirst, 3);
PushBack(&pFirst, 1);
PushBack(&pFirst, 3);
PushBack(&pFirst, 3);
PushBack(&pFirst, 3);
PushBack(&pFirst, 3);
PushBack(&pFirst, 3);
PushBack(&pFirst, 5);
PushBack(&pFirst, 3);
Print(pFirst);
Remove(&pFirst, 3);
Print(pFirst);
RemoveAll(&pFirst, 3);
Print(pFirst);
}
main.c
#include"Hello.h"
int main(){
TestRemove();
//TestSList();
system("pause");
}
到此,单链表的基本功能差不多都实现了。