目录
什么是单链表
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个节点的构成:(元素+指针) 元素就是存储数据的存储单元,指针就是连接每个节点的地址数据。
创建单链表
typedef int SListDate;
//单链表的结构定义
typedef struct SListNode
{
SListDate data;//数据
struct SListNode* next;//结构体指针 next
}SListNode;
//创建节点(动态开辟)
SListNode* BuySListNode(SListDate x)
{
SListNode* node =(SListNode*)malloc(sizeof(SListNode));
node->data = x;
node->next = NULL;
return node;
}
单链表的尾插
可以分为:链表为不为空, 为空开辟一个节点,非空找尾
链表非空
注意我这里的测试接口是定义了一个指针,后面的函数调用时要传二级指针
void TestList1()
{
SListNode* plist = NULL;
SListPushBack(&plist,1);//注意是二级指针
}
int main()
{
TestList1();
return 0;
}
void SListPushBack(SListNode**pplist, SListDate x)
{
SListNode* newnode = BuySListNode(x);
//如果是空链表
if (*pplist == NULL)
{
*pplist = newnode;
}
else
{
//尾插 ->找尾
SListNode* tail = *pplist;//先找到头(tail)
while (tail->next != NULL)
{
tail = tail->next;//类似数组中++的作用
//tail = tail->next找到下一个节点的地址给给tail
}
tail->next = newnode;
}
}
单链表的尾删
有以下几种情况:1.没有节点(没有可删的)
2, 只有1个节点(直接free)
3.多个节点
多个节点先找尾
void SListPopBack(SListNode**pplist)
{
//1.没有节点
//2, 只有1个节点
//3.多个节点
if (*pplist == NULL)//空链表(没有节点)没有可删的
{
return ;
}
//找尾
else if ((*pplist)->next == NULL)//只有一个节点free掉开辟的那个节点
{
free(*pplist);
*pplist = NULL;
}
else
{
SListNode* prev = NULL;
SListNode* tail = *pplist;
while (tail->next != NULL)
{
prve = tail;
tail = tail->next;
}
free(tail);
tail = NULL;
prve->next = NULL;
}
}
单链表的头插
void SListPushFort(SListNode** pplist, SListDate x)
{
SListNode* newnode = BuySListNode(x);
newnode->next = *pplist;//头的地址 plist
*pplist = newnode;// newnode给给*plist成为新的表头
}
单链表的头删
链表为空,或非空
void SListPopFort(SListNode** pplist)
{
//找头
if (*pplist == NULL)
{
return;
}
else
{
SListNode* next = (*pplist)->next;//先存一下要头删的地址
free(*pplist);
*pplist = next;
}
}
单链表查找 (和修改)
SListNode* SListFind(SListNode* plist, SListDate x)
{
SListNode* cur = plist;
//while(cur != NULL)等价于while(cur)
while (cur)//遍历链表
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
修改
SListNode* pos = SListFind(plist, 6);//要查找的数字
if (pos == NULL)
{
printf("没有找到\n");
}
else
{
printf("找到了\n");
pos->data = 30;//修改
}
//SListPrint(plist);
}
单链表打印
void SListPrint(SListNode*plist)
{
SListNode* cur = plist;
while (cur != NULL)
{
printf("%d->",cur->data);
cur = cur->next;//next 结构体指针
//找到下一个不为空的节点(的地址) 并赋值过去
}
printf("NULL");
printf("\n");
}
完整测试代码
linklist.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SListDate;
//单链表的结构定义
typedef struct SListNode
{
SListDate data;//数据
struct SListNode* next;//结构体指针 next
}SListNode;
//单向+不带头+不循环
//打印链表
void SListPrint(SListNode*plist);
//尾插
void SListPushBack(SListNode**pplist, SListDate x);
//头插
void SListPushFort(SListNode**pplist, SListDate x);
//尾删
void SListPopBack(SListNode**pplist);
//头删
void SListPopFort(SListNode**pplist);
//单链表查找
SListNode* SListFind(SListNode* plist, SListDate x);
linklist.c
#include"linklist.h"
void SListPrint(SListNode*plist)
{
SListNode* cur = plist;
while (cur != NULL)
{
printf("%d->",cur->data);
cur = cur->next;//next 结构体指针
//找到下一个不为空的节点(的地址) 并赋值过去
}
printf("NULL");
printf("\n");
}
//创建节点
SListNode* BuySListNode(SListDate x)
{
SListNode* node =(SListNode*)malloc(sizeof(SListNode));
node->data = x;
node->next = NULL;
return node;
}
void SListPushBack(SListNode**pplist, SListDate x)
{
SListNode* newnode = BuySListNode(x);
//如果是空链表
if (*pplist == NULL)
{
*pplist = newnode;
}
else
{
//尾插 ->找尾
SListNode* tail = *pplist;//先找到头(tail)
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newnode;
}
}
void SListPushFort(SListNode** pplist, SListDate x)
{
SListNode* newnode = BuySListNode(x);
newnode->next = *pplist;//头的地址 plist
*pplist = newnode;// newnode给给*plist成为新的表头
}
void SListPopBack(SListNode**pplist)
{
//1.没有节点
//2, 只有1个节点
//3.多个节点
if (*pplist == NULL)//空链表(没有节点)没有可删的
{
return ;
}
//找尾
else if ((*pplist)->next == NULL)//只有一个节点free掉开辟的那个节点
{ //
free(*pplist);
*pplist = NULL;
}
else
{
SListNode* prve = NULL;
SListNode* tail = *pplist;
while (tail->next != NULL)
{
prve = tail;
tail = tail->next;
}
free(tail);
tail = NULL;
prve->next = NULL;
}
}
void SListPopFort(SListNode** pplist)
{
//找头
if (*pplist == NULL)
{
return;
}
else
{
SListNode* next = (*pplist)->next;//先存一下要头删的地址
free(*pplist);
//next 里面存的是头删的地址->下一个节点的地址
*pplist = next;
}
}
SListNode* SListFind(SListNode* plist, SListDate x)
{
SListNode* cur = plist;
//while(cur != NULL)等价于while(cur)
while (cur)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
void SListInsertAfter(SListNode* pos, SListDate x)
{
assert(pos);
SListNode* newnode = BuySListNode(x);
newnode->next = pos->next;
pos->next = newnode;
}
test.c
void TestList1()
{
SListNode* plist = NULL;
SListPushFort(&plist,1);//注意是二级指针
SListPushFort(&plist,2);
SListPushFort(&plist,3);
SListPushFort(&plist,4);
//SListPrint(plist);
SListPushFort(&plist,5);
SListPushFort(&plist, 4);
SListPushFort(&plist, 3);
//SListPopBack(&plist);
//SListPopBack(&plist);
//SListPopBack(&plist);
//SListPopBack(&plist);
//SListPopBack(&plist);
SListPrint(plist);
SListPrint(plist);
}
void TestList2()
{
SListNode* plist = NULL;
SListPushBack(&plist, 1);//注意是二级指针
SListPushBack(&plist, 2);
SListPushBack(&plist, 3);
SListPushBack(&plist, 4);
SListPrint(plist);
SListNode* pos = SListFind(plist, 6);//要查找的数字
if (pos == NULL)
{
printf("没有找到\n");
}
else
{
printf("找到了\n");
//pos->data = 30;//修改
}
SListPrint(plist);
}
int main()
{
TestList1();
return 0;
}