1.单链表的储存结构
cpptypedef int SLTDataType;//链表是由节点组成的 typedef struct SListNode { SLTDataType data; struct SListNode* next; }SLTNode;
typedef的int,因为存储的数据不一定是整型,所以为了以后的修改不必要每个地方都改。
cpp#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指针停止。
cppvoid 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.单链表的各个函数
申请一个节点
cpp//申请一个节点 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遗忘掉
尾插节点
cpp//尾插节点 void SLTPushBack(SLTNode** pphead, SLTDataType x) { assert(pphead); SLTNode* newnodes = SLTBuyNode(x); //链表为空,新节点作为phead if (*pphead == NULL) { *pphead = newnodes; } //链表不为空,找尾节点 else { SLTNode* ptail = *pphead; while (ptail->next) { ptail = ptail->next; } //patil就是尾节点 ptail->next = newnodes; } }
头插节点
cpp//头插节点 void SLTPushFornt(SLTNode** pphead, SLTDataType x) { assert(pphead); SLTNode* newnode = SLTBuyNode(x); newnode->next = *pphead; *pphead = newnode; }
尾删节点
cpp//尾删节点 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; } }
头删节点
cpp//头删节点 void SLTPopFornt(SLTNode** pphead) { assert(pphead); //链表不为空 assert(*pphead); //让第二个节点成为新头 //把旧空间释放 SLTNode* next = (*pphead)->next; free(*pphead); *pphead = next; }
查找节点
cpp//查找节点 SLTNode* SLTFind(SLTNode** pphead, SLTDataType x) { SLTNode* pcur = *pphead; while (pcur) { if (pcur->data == x) { return pcur; } pcur = pcur->next; } return NULL; }
在指定位置前插入数据
cpp//在指定位置之前插入数据 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; }
在指定位置后插入数据
cpp//在指定位置之后插入数据 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; }
在指定位置前删除数据
cpp//删除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; }
在指定位置后删除数据
cpp//删除pos之后节点 void SLTEraseAfter(SLTNode* pos) { assert(pos); assert(pos->next); SLTNode* next = pos->next->next; free(pos->next); pos->next = next; }
销毁链表
cpp//销毁链表 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
cpp#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
cpp#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); //链表为空,新节点作为phead if (*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
cpp#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; }