ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

【数据结构】单链表

2026/9/19 12:50:56 拓冰建站 浏览量
【数据结构】单链表

1.单链表的储存结构

typedef int SLTDataType;//链表是由节点组成的typedef struct SListNode
{SLTDataType data;struct SListNode* next;
}SLTNode;

typedef的int,因为存储的数据不一定是整型,所以为了以后的修改不必要每个地方都改。

#include "SList.h"
int main()
{SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));node1->data = 1;SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));node2->data = 2;SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));node3->data = 3;SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));node4->data = 4;node1->next = node2;node2->next = node3;node3->next = node4;node4->next = NULL;SLTNode* plist = node1;SLTPrint(plist);return 0;
}

2.遍历单链表

依次遍历链表中的每个节点直到遇到NULL指针停止。

void SLTPrint(SLTNode* phead) {SLTNode* pcur = phead;while (pcur){printf("%d->", pcur->data);pcur = pcur->next;}printf("NULL\n");

1.定义pcur是为了不改变原指针的前提下,让pcur往下走.

2.pcur = pcur->next;是链表中的关键代码,作用就是把链表穿起来,phead是指向链表的指针,用pcur代替phead往下走,pcur->next这句话意思是一块空间的后一个部分的指向就是下一块空间的指针,说明这个指针就是指向下一块空间的。

3.

3.单链表的各个函数

申请一个节点

//申请一个节点
SLTNode* SLTBuyNode(SLTDataType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("malloc fail");exit(-1);}newnode->data = x;newnode->next = NULL;return newnode;
}

最后一句return newnode遗忘掉

尾插节点

//尾插节点
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* newnodes = SLTBuyNode(x);//链表为空,新节点作为pheadif (*pphead == NULL){*pphead = newnodes;}//链表不为空,找尾节点else{SLTNode* ptail = *pphead;while (ptail->next){ptail = ptail->next;}//patil就是尾节点ptail->next = newnodes;}
}

头插节点

//头插节点
void SLTPushFornt(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* newnode = SLTBuyNode(x);newnode->next = *pphead;*pphead = newnode;
}

尾删节点

//尾删节点
void SLTPopBack(SLTNode** pphead)
{assert(pphead);//链表为空assert(*pphead);//链表只有一个节点if ((*pphead)->next == NULL){*pphead = NULL;}//链表有多个节点else{SLTNode* ptail = *pphead;SLTNode* prev = NULL;while (ptail->next){prev = ptail;ptail = ptail->next;}free(ptail);ptail = NULL;prev->next = NULL;}
}

头删节点

//头删节点
void SLTPopFornt(SLTNode** pphead)
{assert(pphead);//链表不为空assert(*pphead);//让第二个节点成为新头//把旧空间释放SLTNode* next = (*pphead)->next;free(*pphead);*pphead = next;
}

查找节点

//查找节点
SLTNode* SLTFind(SLTNode** pphead, SLTDataType x)
{SLTNode* pcur = *pphead;while (pcur){if (pcur->data == x){return pcur;}pcur = pcur->next;}return NULL;
}

在指定位置前插入数据

//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead);assert(pos);assert(*pphead);SLTNode* newnode = SLTBuyNode(x);if (pos == *pphead){SLTPushFornt(pphead, x);return;}SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}newnode->next = pos;prev->next = newnode;
}

在指定位置后插入数据

//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = SLTBuyNode(x);/*SLTNode* next = pos->next;newnode->next = next;*/newnode->next = pos->next;pos->next = newnode;
}

在指定位置前删除数据

//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead);assert(*pphead);assert(pos);if (*pphead == pos){SLTPopFornt(pphead);return;}SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}SLTNode* next = pos->next;free(pos);pos = NULL;prev->next = next;
}

在指定位置后删除数据

//删除pos之后节点
void SLTEraseAfter(SLTNode* pos)
{assert(pos);assert(pos->next);SLTNode* next = pos->next->next;free(pos->next);pos->next = next;
}

销毁链表

//销毁链表
void SLTDestory(SLTNode** pphead)
{assert(pphead);assert(*pphead);SLTNode* pcur = *pphead;while (pcur){SLTNode* next = pcur->next;free(pcur);pcur = next;}*pphead = NULL;
}

4.单链表全部代码

SList.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int SLTDataType;//链表是由节点组成的
typedef struct SListNode
{SLTDataType data;struct SListNode* next;
}SLTNode;//打印节点
void SLTPrint(SLTNode* phead);//尾插节点
void SLTPushBack(SLTNode** pphead,SLTDataType x);//头插节点
void SLTPushFornt(SLTNode** pphead, SLTDataType x);//尾删节点
void SLTPopBack(SLTNode** pphead);//头删节点
void SLTPopFornt(SLTNode** pphead);//查找节点
SLTNode* SLTFind(SLTNode* phead,SLTDataType x);//在指定位置插入数据//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead,SLTNode* pos, SLTDataType x);//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x);//在指定位置删除节点//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos);//删除pos之后节点
void SLTEraseAfter(SLTNode* pos);//销毁链表
void SLTDestory(SLTNode** pphead);

SList.c

#define _CRT_SECURE_NO_WARNINGS
#include "SList.h"//打印单链表
void SLTPrint(SLTNode* phead)
{SLTNode* pcur = phead;while (pcur){printf("%d->", pcur->data);pcur = pcur->next;}printf("NULL\n");
}SLTNode* SLTBuyNode(SLTDataType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("malloc fail");exit(-1);}newnode->data = x;newnode->next = NULL;return newnode;
}//尾插节点
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* newnodes = SLTBuyNode(x);//链表为空,新节点作为pheadif (*pphead == NULL){*pphead = newnodes;}//链表为空,找尾节点else{SLTNode* ptail = *pphead;while (ptail->next){ptail = ptail->next;}//patil就是尾节点ptail->next = newnodes;}
}//头插节点
void SLTPushFornt(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* newnode = SLTBuyNode(x);newnode->next = *pphead;*pphead = newnode;
}//尾删节点
void SLTPopBack(SLTNode** pphead)
{assert(pphead);//链表为空assert(*pphead);//链表只有一个节点if ((*pphead)->next == NULL){*pphead = NULL;}//链表有多个节点else{SLTNode* ptail = *pphead;/*	SLTNode* prev = NULL;while (ptail->next){prev = ptail;ptail = ptail->next;}free(ptail);ptail = NULL;prev->next = NULL;*/while (ptail->next->next){ptail = ptail->next;}free(ptail->next);ptail->next = NULL;}
}//头删节点
void SLTPopFornt(SLTNode** pphead)
{assert(pphead);//链表不为空assert(*pphead);//让第二个节点成为新头//把旧空间释放SLTNode* next = (*pphead)->next;free(*pphead);*pphead = next;
}//查找节点
SLTNode* SLTFind(SLTNode** pphead, SLTDataType x)
{SLTNode* pcur = *pphead;while (pcur){if (pcur->data == x){return pcur;}pcur = pcur->next;}return NULL;
}//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead);assert(pos);assert(*pphead);SLTNode* newnode = SLTBuyNode(x);if (pos == *pphead){SLTPushFornt(pphead, x);return;}SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}newnode->next = pos;prev->next = newnode;
}//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = SLTBuyNode(x);/*SLTNode* next = pos->next;newnode->next = next;*/newnode->next = pos->next;pos->next = newnode;
}//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead);assert(*pphead);assert(pos);if (*pphead == pos){SLTPopFornt(pphead);return;}SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}SLTNode* next = pos->next;free(pos);pos = NULL;prev->next = next;
}//删除pos之后节点
void SLTEraseAfter(SLTNode* pos)
{assert(pos);assert(pos->next);SLTNode* next = pos->next->next;free(pos->next);pos->next = next;
}//销毁链表
void SLTDestory(SLTNode** pphead)
{assert(pphead);assert(*pphead);SLTNode* pcur = *pphead;while (pcur){SLTNode* next = pcur->next;free(pcur);pcur = next;}*pphead = NULL;
}

test.c

#define _CRT_SECURE_NO_WARNINGS
#include "SList.h"int main()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPrint(plist);SLTNode* FindRet = SLTFind(&plist, 3);if (FindRet == NULL){printf("找不到\n");}else{printf("找到了\n");}SLTDestory(&plist);return 0;
}