数据结构--单链表的基本操作(插入、删除、逆置、修改)

顺序表与链表的区别

顺序表可以随机存取表中任一个元素,但是插入和删除的时候需要移动大量的元素,这会使得算法的时间复杂度增加。而链式存储线性表时,不需要使用地址连续的存储单元,并不是逻辑上相邻的元素物理上也相邻,通过“链”连接元素之间的逻辑关系,不需要大量移动元素。

实现步骤

存储定义和函数声明

定义链表的结构体指针,数据域与指针域;函数的声明主要包括:链表的初始化(带头结点) 空表的判断、头插法建立单链表、头插结点增加链表结点个数、尾插结点增加链表结点个数、在第len个位置后面插入e的结点、链表的逆置等

/*
 * @Author: 没有神的过往 2840562464@qq.com
 * @Date: 2024-05-15 22:34:13
 * @LastEditTime: 2024-05-17 22:41:31
 * @FilePath: \code\C\LinkList\head.h
 */
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>

#define ElemType int
#define Status int
using namespace std;
typedef struct LNode // 定义单链表结点类型
{
    ElemType data;      // 每一个结点存放一个数据元素
    int length;
    struct LNode *next; // 指针指向下一个结点
} LNode, *Linklist;     // LNode *L (强调这是一个结点)与 Linklist L(强调这是一个单链表)  都是表明声明一个指向单链表第一个结点的指针;

bool InitList(Linklist &L);       // 初始化单链表
bool EmptyList(Linklist &L);      // 判断链表是否为空
Linklist HeadInsert(Linklist &L); // 头插法建立单链表

bool HeadInsert_node(Linklist &L, ElemType e);       // 头插结点
bool EndInsert_node(Linklist &L, ElemType e);        // 尾插结点
bool DeleteList(Linklist &L);                        // 链表的删除,即删除所有的结点;
bool IncreaseList(Linklist &L, int len, ElemType e); // 在第len个元素后面插入数值为e的结点
bool ChangeList(Linklist &L, int len, ElemType e);   // 把第len个元素的值改为e
Linklist InvertedList(Linklist &L);                  // 链表的逆置
void printfList(Linklist &L);                        // 打印链表
void menu();                                         // 打印菜单;

定义操作函数

使用头插法建立单链表HeadInsert,然后主要功能有插入和逆置,具体代码看下面吧

bool InitList(Linklist &L)
{
    L = (LNode *)malloc(sizeof(LNode)); // 分配一个头结点
    if (L == NULL)                      // 如果为空表示分配失败
    {
        return false;
    }
    L->next = NULL;
    return true;
}

bool DeleteList(Linklist &L)
{
    LNode *p;
    p = L;
    while (L->next != NULL)
    {
        L = L->next;
        p->next = L->next;
        free(L);
        L = p;
    }
    if (L->next == NULL)
    {
        printf("删除成功!");
        printfList(L);
        return true;
    }
    return false;
}
bool EmptyList(Linklist &L)
{
    if (L->next == NULL)
    {
        return false;
    }
    return true;
}
bool IncreaseList(Linklist &L, int len, ElemType e)
{
    if (len < 1) // 在第len个位置插入e,时间复杂度为O(n);
    {
        return false;
    }

    int number = 0; // 当前的p指向的是第几个结点
    LNode *p = L;
    while (p != NULL && number < len - 1)
    {
        p = p->next;
        number++;
    }
    if (p == NULL)
    {
        return false;
    }
    LNode *s = (LNode *)malloc(sizeof(LNode));
    s->data = e;
    s->next = p->next;
    p->next = s;
    L->length++;
    return true;
}
Linklist HeadInsert(Linklist &L)
{
    int value;
    if (InitList(L))
    {
        printf("现在使用头插法建立单链表,请输入你要插入的数字,以9999结束:");
        scanf("%d", &value);
        while (value != 9999) // 头插法建立单链表,数值以9999结束;
        {

            LNode *p;
            p = (LNode *)malloc(sizeof(LNode));
            p->data = value;
            p->next = L->next;
            L->next = p;
            L->length++;
            scanf("%d", &value);
        }
        return L;
    }
}

bool HeadInsert_node(Linklist &L, ElemType e)
{
    LNode *p;
    p = (LNode *)malloc(sizeof(LNode));
    p->data = e;
    p->next = L->next;
    L->next = p;
    L->length++;
    return true;
}
bool EndInsert_node(Linklist &L, ElemType e)
{
    LNode *p;
    LNode *s = L;
    p = (LNode *)malloc(sizeof(LNode));
    p->data = e;

    if (EmptyList(L))
    {
        while (s->next != NULL)
        {
            s = s->next;
        }
        p->next = s->next;
        s->next = p;
        L->length++;
        return true;
    }
    return false;
}
bool ChangeList(Linklist &L, int len, ElemType e)
{
    LNode *p = L;
    int number = 0;
    if (len < 1)
    {
        printf("输入的数据不合法!");
        return false;
    }
    while (p->next != NULL && number < len)
    {
        p = p->next;
        number++;
    }
    p->data = e;
    printfList(L);
    return true;
}

Linklist InvertedList(Linklist &L)
{
    LNode *temp = NULL, *PHead = NULL;
    if (L->next == NULL || L->next->next == NULL)
    {
        return L;
    }
    Linklist p = L->next;
    while (p != NULL)
    {
        temp = p;
        p = p->next;
        temp->next = PHead;
        PHead = temp;
    }
    L->next = PHead;
    return L;
}
void printfList(Linklist &L)
{
    LNode *p = L;
    printf("链表的顺序为:");
    while (p->next != NULL)
    {
        p = p->next;
        printf("%d->", p->data);
    }
    if (p->next == NULL)
    {
        printf("链表的长度是%d", L->length);
    }
    printf("\n");
}

定义菜单

定义菜单之后,可以更方便的对链表进行基本操作,而且也会使代码更简洁,美观。

void menu()
{
    printf("****************菜   单*******************\n");
    printf("1.头插法创建链表            2.在位置后面插值\n");
    printf("3.链表数据的修改            4.链表的逆置    \n");
    printf("5.头插元素                 6.尾插元素       \n");
    printf("7.打印链表                                 \n");
    printf("******************************************\n");
}

完整代码

上面的头文件和下面这段代码,添加到一个工程中就可以运行啦!

/*
 * @Author: 没有神的过往 2840562464@qq.com
 * @Date: 2024-05-16 13:14:35
 * @LastEditTime: 2024-05-17 22:10:09
 * @FilePath: \code\C\LinkList\main.cpp
 */
#include "head.h"
int main()
{
    Linklist L;
    int chance = 0;
    int len = 0;
    ElemType e;
    do
    {
        menu();
        printf("请输入你的选择:");
        scanf("%d", &chance);
        switch (chance)
        {
        case 1:
            HeadInsert(L);
            printfList(L);
            break;
        case 2:
            printf("请输入你要插入的位置和元素:");
            scanf("%d %d", &len, &e);
            IncreaseList(L, len, e);
            printfList(L);
            break;
        case 3:
            printf("请输入你要修改的位置和元素:");
            scanf("%d%d", &len, &e);
            ChangeList(L, len, e);
            break;
        case 4:
            Linklist p = InvertedList(L);
            printfList(p);
            break;
        case 5:
            printf("请输入你要头插的元素:");
            scanf("%d", &e);
            HeadInsert_node(L, e);
            printfList(L);
            break;
        case 6:
            printf("请输入你要尾插的元素:");
            scanf("%d", &e);
            EndInsert_node(L, e);
            printfList(L);
            break;
            // default:
            //     break;
        }
    } while (chance >= 1 && chance <= 7);

    getchar();
    return 0;
}
void menu()
{
    printf("****************菜   单*******************\n");
    printf("1.头插法创建链表            2.在位置后面插值\n");
    printf("3.链表数据的修改            4.链表的逆置    \n");
    printf("5.头插元素                 6.尾插元素       \n");
    printf("7.打印链表                                 \n");
    printf("******************************************\n");
}

bool InitList(Linklist &L)
{
    L = (LNode *)malloc(sizeof(LNode)); // 分配一个头结点
    if (L == NULL)                      // 如果为空表示分配失败
    {
        return false;
    }
    L->next = NULL;
    return true;
}

bool DeleteList(Linklist &L)
{
    LNode *p;
    p = L;
    while (L->next != NULL)
    {
        L = L->next;
        p->next = L->next;
        free(L);
        L = p;
    }
    if (L->next == NULL)
    {
        printf("删除成功!");
        printfList(L);
        return true;
    }
    return false;
}
bool EmptyList(Linklist &L)
{
    if (L->next == NULL)
    {
        return false;
    }
    return true;
}
bool IncreaseList(Linklist &L, int len, ElemType e)
{
    if (len < 1) // 在第len个位置插入e,时间复杂度为O(n);
    {
        return false;
    }

    int number = 0; // 当前的p指向的是第几个结点
    LNode *p = L;
    while (p != NULL && number < len - 1)
    {
        p = p->next;
        number++;
    }
    if (p == NULL)
    {
        return false;
    }
    LNode *s = (LNode *)malloc(sizeof(LNode));
    s->data = e;
    s->next = p->next;
    p->next = s;
    L->length++;
    return true;
}
Linklist HeadInsert(Linklist &L)
{
    int value;
    if (InitList(L))
    {
        printf("现在使用头插法建立单链表,请输入你要插入的数字,以9999结束:");
        scanf("%d", &value);
        while (value != 9999) // 头插法建立单链表,数值以9999结束;
        {

            LNode *p;
            p = (LNode *)malloc(sizeof(LNode));
            p->data = value;
            p->next = L->next;
            L->next = p;
            L->length++;
            scanf("%d", &value);
        }
        return L;
    }
}

bool HeadInsert_node(Linklist &L, ElemType e)
{
    LNode *p;
    p = (LNode *)malloc(sizeof(LNode));
    p->data = e;
    p->next = L->next;
    L->next = p;
    L->length++;
    return true;
}
bool EndInsert_node(Linklist &L, ElemType e)
{
    LNode *p;
    LNode *s = L;
    p = (LNode *)malloc(sizeof(LNode));
    p->data = e;

    if (EmptyList(L))
    {
        while (s->next != NULL)
        {
            s = s->next;
        }
        p->next = s->next;
        s->next = p;
        L->length++;
        return true;
    }
    return false;
}
bool ChangeList(Linklist &L, int len, ElemType e)
{
    LNode *p = L;
    int number = 0;
    if (len < 1)
    {
        printf("输入的数据不合法!");
        return false;
    }
    while (p->next != NULL && number < len)
    {
        p = p->next;
        number++;
    }
    p->data = e;
    printfList(L);
    return true;
}

Linklist InvertedList(Linklist &L)
{
    LNode *temp = NULL, *PHead = NULL;
    if (L->next == NULL || L->next->next == NULL)
    {
        return L;
    }
    Linklist p = L->next;
    while (p != NULL)
    {
        temp = p;
        p = p->next;
        temp->next = PHead;
        PHead = temp;
    }
    L->next = PHead;
    return L;
}
void printfList(Linklist &L)
{
    LNode *p = L;
    printf("链表的顺序为:");
    while (p->next != NULL)
    {
        p = p->next;
        printf("%d->", p->data);
    }
    if (p->next == NULL)
    {
        printf("链表的长度是%d", L->length);
    }
    printf("\n");
}

运行结果

运行结果如下:

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值