【数据结构】单链表-增-删-查(C语言)

简介: 【数据结构】单链表-增-删-查(C语言)

我的小站——半生瓜のblog


在这里插入图片描述

@TOC

结构体定义

typedef int SLTDataType;
typedef struct SListNode
{
    SLTDataType data;
    struct SListNode* next;
}SLTNode;

打印

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

创建结点

SLTNode* SLTCreat(SLTDataType x)
{
    SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
    newnode->data = x;
    newnode->next = NULL;
    return newnode;
}

尾插

void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
    //创建新结点
    SLTNode* newnode = SLTCreat(x);
    //如果是空链表
    if (*pphead == NULL)
    {
        *pphead = newnode;
    }
    else
    { 
        //找到尾结点
        SLTNode* tail = *pphead;
        while (tail->next != NULL)
        {
            tail = tail->next;
        }
        tail->next = newnode;
    }
}

头插

void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
    //创建新结点
    SLTNode* newnode = SLTCreat(x);
    newnode->next = *pphead;
    *pphead = newnode;
}

尾删

void SLTPopBack(SLTNode** pphead)
{    
    //空链表
    if (*pphead == NULL)
    {
        return ;
    }
    //链表中只有一个结点
    else if ((*pphead)->next == NULL)
    {
        free(*pphead);
        *pphead = NULL;
    }
    //一个以上结点
    else
    {
        //找到尾结点
        SLTNode* tail = *pphead;
        //找到尾结点的前一个结点
        SLTNode* tailPrev = NULL;
        while (tail->next != NULL)
        {
            tailPrev = tail;
            tail = tail->next;
        }
        free(tail);
        tailPrev->next = NULL;

    }

}

头删

void SLTPopFront(SLTNode** pphead)
{
    //如果直接free pphead就会找不到后面的结点了
    //先保存下一个
    SLTNode* ppheadNext = (*pphead)->next;//这里要加一个括号,因为*和->都是解引用,*是对任意的指针都可以解引用,取它指向的这个位置的数据,什么类型的指针就取几个字节,->是结构体的,这时候他们两个的优先级是一样的。
    free(*pphead);
    //这时候第一个数据就是之前第二个数据了
    *pphead = ppheadNext;
}

查找

下面的删除和插入都要在先在链表中找到为前提。

SLTNode* SLTFind(SLTNode* phead,SLTDataType x)
{
    SLTNode* pos = phead;
    while (pos != NULL)
    { 
        if (pos->data == x)
        {
            return pos;
        }
        pos = pos->next;
    }
    return NULL;
}

在指定位置前插入某个数据

void SLTInsert(SLTNode** pphead,SLTNode* pos, SLTDataType x)
{
    //如果在第一个结点前插入数据
    //那就是头插,直接调用头插的函数
    if (pos == *pphead)
    {
        SLTPushFront(pphead,x);
    }
    else
    {
        //创建一个新结点来存放新的数据
        SLTNode* newnode = SLTCreat(x);
        //要在pos前面插入newnode,就得先找到pos前面的内个结点
        SLTNode* posPrev = *pphead;
        while (posPrev->next != pos)
        {
            posPrev = posPrev->next;
        }
        //链接起来
        posPrev->next = newnode;
        newnode->next = pos;
    }
}

删除指定位置数据

void SLTErase(SLTNode** pphead, SLTNode*pos)
{
    //当删除第一个结点的时候,无法找到他的前一个结点
    if (pos == *pphead)
    {
        SLTPopFront(pphead);
    }
    else
    {
        //单链表每次老是要寻找前一个结点
        SLTNode* posPrev = *pphead;
        while (posPrev->next != pos)
        {
            posPrev = posPrev->next;
        }
        posPrev->next = pos->next;
        free(pos);
    }
}

全部代码

#include<stdio.h>
#include<stdlib.h>
//定义结构
typedef int SLTDataType;
typedef struct SListNode
{
    SLTDataType data;
    struct SListNode* next;
}SLTNode;
//改变头结点的传2级指针,不改变的传1级指针
//打印
void SLTPrint(SLTNode* phead)
{
    SLTNode* cur = phead;
    while (cur !=NULL)
    {
        printf("%d ", cur->data);
        cur = cur->next;
    }
    printf("\n");
}
//创建结点
SLTNode* SLTCreat(SLTDataType x)
{
    SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
    newnode->data = x;
    newnode->next = NULL;
    return newnode;
}
//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
    //创建新结点
    SLTNode* newnode = SLTCreat(x);
    //如果是空链表
    if (*pphead == NULL)
    {
        *pphead = newnode;
    }
    else
    { 
        //找到尾结点
        SLTNode* tail = *pphead;
        while (tail->next != NULL)
        {
            tail = tail->next;
        }
        tail->next = newnode;
    }
}
//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
    //创建新结点
    SLTNode* newnode = SLTCreat(x);
    newnode->next = *pphead;
    *pphead = newnode;
}
//尾删
void SLTPopBack(SLTNode** pphead)
{    
    //空链表
    if (*pphead == NULL)
    {
        return ;
    }
    //链表中只有一个结点
    else if ((*pphead)->next == NULL)
    {
        free(*pphead);
        *pphead = NULL;
    }
    //一个以上结点
    else
    {
        //找到尾结点
        SLTNode* tail = *pphead;
        //找到尾结点的前一个结点
        SLTNode* tailPrev = NULL;
        while (tail->next != NULL)
        {
            tailPrev = tail;
            tail = tail->next;
        }
        free(tail);
        tailPrev->next = NULL;

    }

}
//头删
void SLTPopFront(SLTNode** pphead)
{
    //如果直接free pphead就会找不到后面的结点了
    //先保存下一个
    SLTNode* ppheadNext = (*pphead)->next;//这里要加一个括号,因为*和->都是解引用,*是对任意的指针都可以解引用,取它指向的这个位置的数据,什么类型的指针就取几个字节,->是结构体的,这时候他们两个的优先级是一样的。
    free(*pphead);
    //这时候第一个数据就是之前第二个数据了
    *pphead = ppheadNext;
}
//查找
SLTNode* SLTFind(SLTNode* phead,SLTDataType x)
{
    SLTNode* pos = phead;
    while (pos != NULL)
    { 
        if (pos->data == x)
        {
            return pos;
        }
        pos = pos->next;
    }
    return NULL;
}
//在pos前插入某个数据
void SLTInsert(SLTNode** pphead,SLTNode* pos, SLTDataType x)
{
    //如果在第一个结点前插入数据
    //那就是头插,直接调用头插的函数
    if (pos == *pphead)
    {
        SLTPushFront(pphead,x);
    }
    else
    {
        //创建一个新结点来存放新的数据
        SLTNode* newnode = SLTCreat(x);
        //要在pos前面插入newnode,就得先找到pos前面的内个结点
        SLTNode* posPrev = *pphead;
        while (posPrev->next != pos)
        {
            posPrev = posPrev->next;
        }
        //链接起来
        posPrev->next = newnode;
        newnode->next = pos;
    }
}
//删除pos位置的数据
void SLTErase(SLTNode** pphead, SLTNode*pos)
{
    //当删除第一个结点的时候,无法找到他的前一个结点
    if (pos == *pphead)
    {
        SLTPopFront(pphead);
    }
    else
    {
        //单链表每次老是要寻找前一个结点
        SLTNode* posPrev = *pphead;
        while (posPrev->next != pos)
        {
            posPrev = posPrev->next;
        }
        posPrev->next = pos->next;
        free(pos);
    }
}
//测试
void Test1()
{
    SLTNode* plist = NULL;
    SLTPushBack(&plist, 0);
    SLTPushBack(&plist, 2);
    SLTPushBack(&plist, 3);
    SLTPushBack(&plist, 4);
    SLTPrint(plist);

    SLTNode* pos = SLTFind(plist, 0);
    if (pos != NULL)
    {
        //说明找到了
        SLTErase(&plist, pos);
    }
    SLTPrint(plist);
    

}
int main(void)
{
    Test1();
    return 0;
}
相关文章
|
25天前
|
存储 编译器 C语言
【数据结构】C语言实现链队列(附完整运行代码)
【数据结构】C语言实现链队列(附完整运行代码)
36 0
|
25天前
|
存储 算法 程序员
【数据结构】C语言实现顺序表万字详解(附完整运行代码)
【数据结构】C语言实现顺序表万字详解(附完整运行代码)
38 0
|
28天前
|
存储 算法 索引
数据结构与算法:单链表
朋友们大家好,本节来到数据结构与算法的新内容:单链表 在上篇文章中,我们知道顺序表通常需要预分配一个固定大小的内存空间, 通常以二倍的大小进行增容,可能会造成空间的浪费,本篇文章我们介绍的链表可以解决这个问题
|
1月前
|
存储
【单链表】数据结构单链表的实现
【单链表】数据结构单链表的实现
|
存储
数据结构--单链表
数据结构--单链表
|
1月前
【数据结构】单链表之--无头单向非循环链表
【数据结构】单链表之--无头单向非循环链表
|
7天前
|
存储 算法
单链表——“数据结构与算法”
单链表——“数据结构与算法”
|
21天前
|
算法 C语言
【算法与数据结构】 C语言实现单链表队列详解2
【算法与数据结构】 C语言实现单链表队列详解
|
21天前
|
存储 算法 C语言
【算法与数据结构】 C语言实现单链表队列详解1
【算法与数据结构】 C语言实现单链表队列详解
|
21天前
|
缓存 算法 搜索推荐
【数据结构】链表(单链表与双链表实现+原理+源码)
【数据结构】链表(单链表与双链表实现+原理+源码)