目录
1.链表的概念及结构
2.链表的实现
2.1链表的创建
2.2结点的创建
2.3从头部插入数据
2.4链表的打印
2.5从尾部插入数据
2.6从尾部删除数据
2.7从头部删除数据
2.8在链表中查找数据
2.9修改链表中的数据
2.10在单链表中的pos之前插入数据
2.11在单链表中的pos之后插入数据
2.12在单链表中的pos之前删除数据
2.13在单链表中的pos之后删除数据
3.完整代码
头文件:SList.h
#pragma once
// 头文件的包含
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
//链表的创建
typedef int SLTDataType;
typedef struct SLTNode
{
SLTDataType data;
struct SLTNode* next;
}SLTNode;
//函数的声明
//打印链表
void SLPrint(SLTNode* phead);
//创建节点
SLTNode* BuySLTNode(SLTDataType x);
//头插
void SLPushFront(SLTNode** pphead, SLTDataType x);
//尾插
void SLPushBack(SLTNode** pphead, SLTDataType x);
//尾删
void SLPopBack(SLTNode** pphead);
//头删
void SLPopFront(SLTNode** pphead);
//查找
SLTNode* SLFindNode(SLTNode* phead, SLTDataType x);
//单链表在pos之前插入数据
void SLInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
// 单链表在pos位置之后插入x
void SLInsertAfter(SLTNode* pos, SLTDataType x);
// 单链表在pos位置之前删除
void SLErase(SLTNode** pphead, SLTNode* pos);
// 单链表在pos位置之后删除
void SLEraseAfter(SLTNode* pos);
源文件:SList.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "SList.h"
//打印
void SLPrint(SLTNode* phead)
{
SLTNode* cur = phead;
while (cur) //判断是否为NULL
{
printf("%d->", cur->data);
cur = cur->next; //指向下一个结点
}
printf("NULL\n");
}
//创建节点
SLTNode* BuySLTNode(SLTDataType x)
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
if (newnode == NULL)
{
perror("malloc fail");
return NULL;
}
newnode->data = x;
newnode->next = NULL;
return newnode;
}
//头插
void SLPushFront(SLTNode** pphead, SLTDataType x)
{
assert(pphead); //防止传参错误导致空指针
SLTNode* newnode = BuySLTNode(x); //创建要插入的结点
newnode->next = *pphead; //改变新节点的下一个指向
*pphead = newnode; //改变头指针的指向
}
//尾插
void SLPushBack(SLTNode** pphead, SLTDataType x)
{
assert(pphead);
SLTNode* newnode = BuySLTNode(x); //创建结点
if (*pphead == NULL) //判断链表是否为空
{
*pphead = newnode; //若为空直接进行插入
}
else
{
SLTNode* tail = *pphead; //找尾结点
while (tail->next)
{
tail = tail->next;
}
tail->next = newnode; //改变尾结点的指向
}
}
//尾删
方法一:记录尾节点的上一个节点
//void SLPopBack(SLTNode** pphead)
//{
// //为空
// assert(pphead);
// assert(*pphead);
// //只有一个节点
// if ((*pphead)->next == NULL)
// {
// free(*pphead);
// *pphead = NULL;
// }
// else
// {
// SLTNode* tail = *pphead;
// SLTNode* Prev = *pphead;
// while (tail->next)
// {
// Prev = tail;
// tail = tail->next;
// }
// free(Prev->next);
// Prev->next = NULL;
// }
//}
//方法二:直接通过next指向的next来释放
void SLPopBack(SLTNode** pphead)
{
//为空
assert(*pphead);
assert(pphead);
//只有一个节点
if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
else
{
SLTNode* tail = *pphead;
while (tail->next->next)
{
tail = tail->next;
}
free(tail->next);
tail->next = NULL;
}
}
//头删
void SLPopFront(SLTNode** pphead)
{
//为空
assert(*pphead);
assert(pphead);
只有一个节点
//if ((*pphead)->next == NULL)
//{
// free(*pphead);
// *pphead = NULL;
//}
//else
//{
// SLTNode* Del = *pphead;
// *pphead = (*pphead)->next;
// free(Del);
// Del = NULL;
//}
//优化
SLTNode* Del = *pphead;
*pphead = (*pphead)->next;
free(Del);
Del = NULL;
}
//查找
SLTNode* SLFindNode(SLTNode* phead, SLTDataType x)
{
SLTNode* cur = phead;
while (cur)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
//单链表在pos之前插入数据
void SLInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
assert(pos);
assert(pphead);
SLTNode* prev = *pphead; //记录前一个结点
SLTNode* newnode = BuySLTNode(x); //创建结点
//如果pos就在头指针的位置,那么就是进行头插的过程
if (*pphead == pos)
{
SLPushFront(pphead, x);
}
else
{
while (prev->next != pos) //找到前一个结点
{
prev = prev->next;
}
prev->next = newnode; //改变指向
newnode->next = pos;
}
}
//在pos后面的位置插入数据
void SLInsertAfter(SLTNode* pos, SLTDataType x)
{
assert(pos);
SLTNode* newnode = BuySLTNode(x);
newnode->next = pos->next;
pos->next = newnode;
}
// 单链表在pos位置之前删除
void SLErase(SLTNode** pphead, SLTNode* pos)
{
assert(pos);
assert(pphead);
if (pos == *pphead)
{
SLPopFront(pphead);
}
else
{
SLTNode* prev = *pphead; //记录前一个结点
while (prev->next != pos) //找到前一个结点
{
prev = prev->next;
}
prev->next = pos->next;
free(pos);
pos = NULL;
}
}
// 单链表在pos位置之后删除
void SLEraseAfter(SLTNode* pos)
{
assert(pos);
if (pos->next)
{
SLTNode* next = pos->next;
SLTNode* nextnext = next->next;
pos->next = nextnext;
free(next);
next = NULL;
}
}
源文件:Test.c
#define _CRT_SECURE_NO_WARNINGS 1
//数据结构: 单链表
#include "SList.h"
void TestSLTNode1()
{
SLTNode* plist = NULL;
//头插
SLPushFront(&plist, 1);
SLPushFront(&plist, 2);
SLPrint(plist);
//尾插
SLPushBack(&plist, 0);
SLPushBack(&plist, -1);
SLPrint(plist);
//头删
SLPopFront(&plist);
SLPrint(plist);
//尾删
SLPopBack(&plist);
SLPrint(plist);
//查找
SLTNode* mark = SLFindNode(plist, 1);
//修改
if (mark != NULL) //判断是否找到了
{
mark->data = 10;
}
SLPrint(plist);
//在pos1之前插入数据
SLTNode* pos1 = SLFindNode(plist, 10);
if (pos1 != NULL)
{
SLInsert(&plist, pos1, 100);
}
SLPrint(plist);
//在pos2之后插入数据
SLTNode* pos2 = SLFindNode(plist, 10);
if (pos2 != NULL)
{
SLInsertAfter(pos2, 100);
}
SLPrint(plist);
//删除pos3之前的数据
SLTNode* pos3 = SLFindNode(plist, 10);
if (pos3 != NULL)
{
SLErase(&plist, pos3);
}
SLPrint(plist);
//删除pos4之后的数据
SLTNode* pos4 = SLFindNode(plist, 10);
if (pos4 != NULL)
{
SLEraseAfter(pos4);
}
SLPrint(plist);
}
int main()
{
TestSLTNode1();
return 0;
}