【数据结构】 双链表的基本操作 (C语言版)

news2025/1/12 8:01:01

目录

一、双链表

1、双链表的定义:

2、双链表表的优缺点: 

二、双链表的基本操作算法(C语言)

 1、宏定义

 2、创建结构体

3、双链表的初始化 

4、双链表表插入

5、双链表的查找

6、双链表的取值

7、求双链表长度

8、双链表的删除

9、双链表的清空

10、双链表的销毁

11、输出链表元素

三、双链表的全部代码(C语言)

四、运行结果


一、双链表

1、双链表的定义:

双链表也叫双向链表,是一种链表数据结构。它的每个数据结点包含两个指针,一个指向前一个结点,另一个指向后一个结点。这意味着从双向链表的任何节点都可以方便地访问其前驱或后继节点。通常,我们构造双向循环链表,它的特点是尾节点的指针域指向头结点,整个链表形成一个环。

 

2、双链表表的优缺点: 

双链表的优点:

  1. 可以方便地访问前驱和后继节点,既可以向前也可以向后遍历链表。
  2. 在某些情况下,双链表比单链表更节省空间,因为它不需要额外的指针来存储前驱和后继节点的信息。

双链表的缺点:

  1. 插入和删除节点相对复杂,需要更多的时间来调整指针。
  2. 双链表需要更多的存储空间,因为每个节点都需要额外的指针来存储前驱和后继节点的信息。

二、双链表的基本操作算法(C语言)

 1、宏定义
#define OK 1
#define ERROR 0

typedef char ElemType;
typedef int Status;
 2、创建结构体
typedef struct DuLNode {
    ElemType data;
    struct DuLNode *prior;
    struct DuLNode *next;
} DuLNode, *DuLinkList;
3、双链表的初始化 
//双链表初始化
Status DInitList(DuLinkList &head) {
    head = new DuLNode;
    head->prior = NULL;
    head->next = NULL;
    return OK;
}
4、双链表表插入
//插入
Status DListInsert(DuLinkList &head, int i, ElemType e) {
    DuLinkList p = head;
    int j = 0;
    while (p && (j < i - 1)) {
        p = p->next;
        ++j;
    }
    if (!p || j > i - 1) {
        return ERROR;
    }

    DuLNode *s = new DuLNode;
    s->data = e;
    s->next = p->next;
    if(p->next != NULL){
      p->next->prior = s;	
    }
    p->next = s;
    s->prior = p;

    return OK;
}
5、双链表的查找

//查找
int DLocateLinkListElem(DuLinkList head, ElemType e) {
    DuLinkList p = head->next;
    int j = 1;
    while (p && (p->data != e)) {
        p = p->next;
        j++;
    }
    if (p == NULL) { 
        return 0;
    }
    return j;
}
6、双链表的取值
//取值
Status DGetLinkList(DuLinkList head, int i, ElemType &e) {
    DuLinkList p = head->next;
    int j = 1;
    while (p && j < i) {
        p = p->next;
        ++j;
    }
    if (p == NULL) {
        return ERROR;
    }
    e = p->data;

    return OK;
}
7、求双链表长度
//求双链表长度
Status DGetLinkListLength(DuLinkList head) {
    DuLinkList p = head->next;
    int length = 0;
    while (p!=NULL) {            //单链表不为空表时
        length++;
        p = p->next;
    }
    return length;
}
8、双链表的删除
//删除
Status DListDelete(DuLinkList &head, int i, ElemType &e) {
    DuLinkList p = head;
    int j = 0;
    while (p && j < i - 1) {
        p = p->next;
        j++;
    }

    if (!p) {
        return ERROR;
    }
    DuLinkList q = p->next;
    e = q->data;
	p->next = q->next;
    if(q->next != NULL){
    	q->next->prior=p;
    }
    delete q;
    return OK;
}
9、双链表的清空
//清空
Status DClearLinkList(DuLinkList &head) {
    DuLinkList p = head->next;
    DuLinkList q;
    while (p) {
        q = p;
        p = p->next;
        delete q;
    }
    head->next = NULL;
    return OK;
}
10、双链表的销毁
//销毁
Status DestoryDLinkList(DuLinkList &head) {
    DuLinkList p;
    while (head) {
        p = head;
        head = head->next;
        delete p;
    }
    return OK;
}
11、输出链表元素
//输出链表元素
void DprintLinkList(DuLinkList head) {
    DuLinkList p = head->next;
    while (p) {
        printf("%c", p->data);
        p = p->next;
    }
    printf("\n");
}

三、双链表的全部代码(C语言)

#include <stdio.h>

#define OK 1
#define ERROR 0

typedef char ElemType;
typedef int Status;

typedef struct DuLNode {
    ElemType data;
    struct DuLNode *prior;
    struct DuLNode *next;
} DuLNode, *DuLinkList;

//双链表初始化
Status DInitList(DuLinkList &head) {
    head = new DuLNode;
    head->prior = NULL;
    head->next = NULL;
    return OK;
}

//功能菜单
int choice() {
    printf("==================================\n");
    printf("         双链表操作功能菜单        \n");
    printf("1、插入元素  2、查询表长  3、按位查找\n");
    printf("4、按值查找  5、删除元素  6、销毁链表\n");
    printf("7、清空链表  8、批量插入  9、链表元素\n");
    printf("==================================\n");
    return 0;
}

//插入
Status DListInsert(DuLinkList &head, int i, ElemType e) {
    DuLinkList p = head;
    int j = 0;
    while (p && (j < i - 1)) {
        p = p->next;
        ++j;
    }
    if (!p || j > i - 1) {
        return ERROR;
    }

    DuLNode *s = new DuLNode;
    s->data = e;
    s->next = p->next;
    if(p->next != NULL){
      p->next->prior = s;	
    }
    p->next = s;
    s->prior = p;

    return OK;
}

//查找
int DLocateLinkListElem(DuLinkList head, ElemType e) {
    DuLinkList p = head->next;
    int j = 1;
    while (p && (p->data != e)) {
        p = p->next;
        j++;
    }
    if (p == NULL) { 
        return 0;
    }
    return j;
}

//取值
Status DGetLinkList(DuLinkList head, int i, ElemType &e) {
    DuLinkList p = head->next;
    int j = 1;
    while (p && j < i) {
        p = p->next;
        ++j;
    }
    if (p == NULL) {
        return ERROR;
    }
    e = p->data;

    return OK;
}

//求双链表长度
Status DGetLinkListLength(DuLinkList head) {
    DuLinkList p = head->next;
    int length = 0;
    while (p!=NULL) {            //单链表不为空表时
        length++;
        p = p->next;
    }
    return length;
}


//删除
Status DListDelete(DuLinkList &head, int i, ElemType &e) {
    DuLinkList p = head;
    int j = 0;
    while (p && j < i - 1) {
        p = p->next;
        j++;
    }

    if (!p) {
        return ERROR;
    }
    DuLinkList q = p->next;
    e = q->data;
	p->next = q->next;
    if(q->next != NULL){
    	q->next->prior=p;
    }
    delete q;
    return OK;
}


//清空
Status DClearLinkList(DuLinkList &head) {
    DuLinkList p = head->next;
    DuLinkList q;
    while (p) {
        q = p;
        p = p->next;
        delete q;
    }
    head->next = NULL;
    return OK;
}

//销毁
Status DestoryDLinkList(DuLinkList &head) {
    DuLinkList p;
    while (head) {
        p = head;
        head = head->next;
        delete p;
    }
    return OK;
}

//输出链表元素
void DprintLinkList(DuLinkList head) {
    DuLinkList p = head->next;
    while (p) {
        printf("%c", p->data);
        p = p->next;
    }
    printf("\n");
}

int main() {

    DuLinkList Dlist;

    printf("双链表正在初始化....\n");
    int InitStatus = DInitList(Dlist);
    if (InitStatus == OK) {
        printf("双链表初始化成功!\n");
    } else {
        printf("双链表初始化失败!\n");
    }

    choice();

    while (1) {
        int flag;
        printf("请输入所需的功能编号:\n");
        scanf("%d", &flag);

        switch (flag) {//通过开关进行功能选择
            case 1: {//插入元素
                //ListInsert_Dul(Dlist,1,'a');
                int insertIndex;
                ElemType inserElem;
                printf("请输入插入元素位置及插入元素(请在英文状态下输入例如:1,a): \n");
                scanf("%d,%c", &insertIndex, &inserElem);
                Status InsertS = DListInsert(Dlist, insertIndex, inserElem);
                if (InsertS == OK) {
                    printf("向双链表%d个位置,插入元素为%c成功!\n\n", insertIndex, inserElem);
                } else {
                    printf("向双链表插入元素失败!\n\n");
                }
            }
                break;
            case 2: {//求单链表的长度
                int length = DGetLinkListLength(Dlist);
                printf("循环双链表的长度为:%d。 \n\n", length);
            }
                break;
            case 3: {//取值
                Status GetIndex;
                printf("请输入需要查询的元素的位置:\n");
                scanf("%d", &GetIndex);
                ElemType GetElem;
                int GetStatus = DGetLinkList(Dlist, GetIndex, GetElem);
                if (GetStatus == OK) {
                    printf("从单链表中获取第%d位置元素成功,所获取到的元素为:%c。\n\n", GetIndex, GetElem);
                } else {
                    printf("从单链表中获取第%d位置元素失败!\n\n", GetIndex);
                }
            }
                break;
            case 4: {//查找
                ElemType LocateElem;
                printf("请输入想要查找元素:\n");
                getchar();    //用于接收回车
                scanf("%c", &LocateElem);
                Status LocateIndex = DLocateLinkListElem(Dlist, LocateElem);
                if (LocateIndex > 0) {
                    printf("从双链表中查找元素%c成功,它在循环链表中的位置为第%d个!\n\n", LocateElem, LocateIndex);
                } else {
                    printf("从双链表中查找元素%c失败!\n\n", LocateElem);
                }
            }
                break;
            case 5: {//删除
                //ListDelete_DuL(list,1);
                Status DeleteIndex;
                printf("请输入想要删除元素的位置:\n");
                scanf("%d", &DeleteIndex);
                ElemType DeleteElem;
                ElemType DeleteStatus = DListDelete(Dlist, DeleteIndex, DeleteElem);
                if (DeleteStatus == OK) {
                    printf("删除双链表第%d个位置的元素成功,删除的元素为:%c。\n\n", DeleteIndex, DeleteElem);
                } else {
                    printf("删除双链表第%d个位置的元素失败!\n\n", DeleteIndex);
                }
            }
                break;
            case 6: {//销毁
                Status DestoryStatus = DestoryDLinkList(Dlist);
                if (DestoryStatus == OK) {
                    printf("双环链表销毁成功!\n\n");
                } else {
                    printf("双链表销毁失败!\n\n");
                }
            }
                break;
            case 7: {//清空
                Status ClearStatus = DClearLinkList(Dlist);
                if (ClearStatus == OK) {
                    printf("双链表清空成功!\n\n");
                } else {
                    printf("双链表清空失败!\n\n");
                }
            }
                break;
            case 8: {//批量插入
                int on;
                printf("请输入想要插入的元素个数:\n");
                scanf("%d", &on);
                ElemType array[on];
                for (int i = 1; i <= on; i++) {
                    getchar();
                    printf("向双链表第%d个位置插入元素为:", (i));
                    scanf("%c", &array[i]);
                }

                for (int i = 1; i <= on; i++) {
                    Status InsertStatus = DListInsert(Dlist, i, array[i]);
                    if (InsertStatus == OK) {
                        printf("向双链表第%d个位置插入元素%c成功!\n", i, array[i]);
                    } else {
                        printf("向双链表第%d个位置插入元素%c失败!\n", i, array[i]);
                    }
                }
            }
                break;
            case 9: {//输出链表元素
                DprintLinkList(Dlist);
            }
                break;
               
            default: {
                printf("输入错误,无此功能,请检查输入:\n\n");
            }
        }
    }

    return 1;

}

四、运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1401656.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华南理工大学数字信号处理实验实验一(薛y老师版本)matlab源码

一、实验目的 1、加深对离散信号频谱分析的理解&#xff1b; 2、分析不同加窗长度对信号频谱的影响&#xff1b; 3、理解频率分辨率的概念&#xff0c;并分析其对频谱的 影响&#xff1b; 4、窗长和补零对DFT的影响 实验源码&#xff1a; 第一题&#xff1a; % 定义离散信…

C++函数对象-函数包装器-调用空的 std::function 时抛出的异常(std::bad_function_call)

任何定义了函数调用操作符的对象都是函数对象。C 支持创建、操作新的函数对象&#xff0c;同时也提供了许多内置的函数对象。 函数包装器 std::function 提供存储任意类型函数对象的支持。 用空的 std::function 时抛出的异常 std::bad_function_call class bad_function_cal…

【C++】命名空间(namespace)

文章目录 1. 为什么要有命名空间?2. 命名空间介绍3.命名空间三种使用方式4. 注意 1. 为什么要有命名空间? 在C语言中&#xff0c;局部变量和全局变量如果同名&#xff0c;在使用时可能会造成冲突。这并不是想避免就能避免的&#xff0c;在程序中&#xff0c;不仅仅是变量&…

《WebKit 技术内幕》之八(2):硬件加速机制

2 Chromium的硬件加速机制 2.1 GraphicsLayer的支持 GraphicsLayer对象是对一个渲染后端存储中某一层的抽象&#xff0c;同众多其他WebKit所定义的抽象类一样&#xff0c;在WebKit移植中&#xff0c;它还需要具体的实现类来支持该类所要提供的功能。为了完成这一功能&#x…

系统架构设计师教程(十三)层次式架构设计理论与实践

层次式架构设计理论与实践 13.1 层次式体系结构概述13.2 表现层框架设计13.2.1 表现层设计模式13.2.2 使用XML设计表现层&#xff0c;统一Web Form与Windows Form的外观13.2.3表现层中UIP设计思想13.2.4 表现层动态生成设计思想 13.3 中间层架构设计13.3.1 业务逻辑层组件设计1…

【Elasticsearch】索引恢复(recovery)流程梳理之副本分片数据恢复

replica shard重启具体流程 replica shard node &#xff08;generic threadpool&#xff09; 也是因为应用新的集群状态触发recovery&#xff0c;进入index阶段进入translog 阶段。先尝试重放本地的translog到global checkpoint向primary shard发起start recovery的请求&…

JVM对象创建与内存回收机制

对象的创建过程有如下步骤&#xff1a; 1.类加载检查&#xff1a; 虚拟机遇到一个new指令时&#xff0c;首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用&#xff0c;并且检查这个符号引用代表的类是否已被加载、解析和初始化过&#xff0c;如果没…

【golang】Context超时控制与原理

Context 在Go语言圈子中流行着一句话&#xff1a; Never start a goroutine without knowing how it will stop。 翻译&#xff1a;如果你不知道协程如何退出&#xff0c;就不要使用它。 在创建协程时&#xff0c;我们可能还会再创建一些别的子协程&#xff0c;那么这些协程的…

【书籍】强化学习第二版(英文版电子版下载、github源码)-附copilot翻译的中英文目录...

Python代码&#xff1a;https://github.com/ShangtongZhang/reinforcement-learning-an-introduction 英文原版书籍下载&#xff1a;http://incompleteideas.net/book/the-book-2nd.html 作者&#xff1a; 理查德S萨顿是阿尔伯塔大学计算机科学教授和强化学习与人工智能 AITF 主…

1.6万字全面掌握 BERT:自然语言处理(NLP)从初学到高级的全面指南

BERT&#xff08;双向编码器表示来自Transformer的模型&#xff09;是由Google开发的一种革命性的自然语言处理&#xff08;NLP&#xff09;模型。它改变了语言理解任务的格局&#xff0c;使机器能够理解语言中的上下文和细微差异。 在本博客中&#xff0c;我们将带您从 BERT …

信息安全概述

信息安全&#xff1a;防止任何对数据进行未授权访问的措施&#xff0c;或者防止造成信息有意无意泄漏、破坏、丢失等问题的发生&#xff0c;让数据处于远离危险、免于威胁的状态或特性。 网络安全&#xff1a;计算机网络环境下的信息安全。 信息安全现状及挑战 数字化时代威…

什么是VUE 创建第一个VUE实例

一、什么是Vue 概念&#xff1a;Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套 构建用户界面 的 渐进式 框架 Vue2官网&#xff1a;Vue.js 1.什么是构建用户界面 基于数据渲染出用户可以看到的界面 2.什么是渐进式 所谓渐进式就是循序渐进&#xff0c;不一定非得把Vu…

Docker编译多平台文件、构建多平台镜像并运行

参考官方文档&#xff1a; Multi-stageMulti-platformMulti-platform images 文章目录 方法Buildx 设置使用QEMU仿真编译文件构建镜像 使用交叉编译&#xff08;cross-compilation&#xff09;编译文件构建镜像 在x86_64上运行arm64容器 方法 如果在 x86_64/amd64 的平台上&am…

Docker 操作之数据卷挂载【云原生】

文章目录 1. 镜像1.1 基本命令1.2 案例练习 2. 容器2.1 基本命令2.2 Nginx 案例2.3 Redis 案例 3. 数据卷3.1 基本命令3.2 Nginx 案例3.3 MySQL 案例 1. 镜像 镜像命令一般分两部分组成&#xff1a;repository:tag。比如 mysql:5.7&#xff0c;表示名称加版本。 在没有指定 t…

一文掌握Python所有常见的循环用法

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 循环是编程中的重要概念&#xff0c;它允许我们重复执行一组操作&#xff0c;直到满足某个条件。Python提供了多种类型的循环&#xff0c;以适应不同的需求和场景。本文将详细介绍Python中所有常见的循环用法&am…

MySQL下对[表]的操作数据类型

目录 表的操作 创建表&#xff1a; 查看表结构&#xff1a; 修改表&#xff1a; 删除表&#xff1a; 数据类型 数据类型分类&#xff1a; 数值类型&#xff1a; tinyint类型越界测试&#xff1a; bit类型&#xff1a; 小数类型&#xff1a; 字符串类型&#xff1a; …

JAVA中 Lambda 方法引用 算法

算法和数据结构 一、Arrays类 接下来学习的类叫做Arrays&#xff0c;其实Arrays并不是重点&#xff0c;但是我们通过Arrays这个类的学习有助于我们理解下一个知识点Lambda的学习。所以我们这里先学习Arrays&#xff0c;再通过Arrays来学习Lamdba这样学习会更丝滑一些_. 1.1 …

【Qt Quick 项目(第一集Qt Quick UI 项目项目创建)】

# Qt Quick 项目 到底什么是Qt Qml、什么是Qt Quick、QtQuick应用程序与Qt Widget程序有何区别,为了让读者在学习QML之前有一个整体认识,这里先介绍几个Quick项目。 01 Qt Quick UI 项目

Java8的Stream最佳实践

从这一篇文章开始&#xff0c;我们会由浅入深&#xff0c;全面的学习stream API的最佳实践&#xff08;结合我的使用经验&#xff09;&#xff0c;本想一篇写完&#xff0c;但写着写着发现需要写的内容太多了&#xff0c;所以分成一个系列慢慢来说。给大家分享我的经验的同时&a…

【博士每天一篇论文-技术综述】Machine Learning With Echo State Networks 一篇系统讲解ESN知识的五星文章

阅读时间&#xff1a;2023-11-21 1 介绍 年份&#xff1a;2020 作者&#xff1a;徐元超&#xff0c;曼尼托巴大学 期刊&#xff1a; 无 引用量&#xff1a;无 这篇文章是一篇技术报告&#xff0c;从递归神经网络&#xff08;RNNs&#xff09;引入到回声状态网络&#xff08;…