带头结点的双向循环链表操作集

news2024/11/25 14:25:30

分数 50

作者 伍建全

单位 重庆科技大学

本题要求实现一个带头结点的双向循环链表操作集。

函数接口定义:

typedef int dataType;

typedef struct _node
{
    dataType data;
    struct _node *prev;//指向前驱的指针
    struct _node *next;//指向后继的指针
}node;

typedef node* List;

//创建一个空的循环链表,返回指向头节点的指针。
List create_list();
//用尾插法向链表L中插入数据域等于x的结点
void insert(List L, dataType x);
//如果链表为空,则返回true,否则返回false。
bool is_empty(List L);
//顺序遍历链表L。输出所有结点的数据域。如果链表为空则输出NULL
void traverse(List L);
//逆序遍历链表L。输出所有结点的数据域。如果链表为空则输出NULL
void traverse_back(List L);
//返回第1个指向数据域等于x的结点的指针。如果没有则返回NULL。
node* search(List L, dataType x);
//删除指针p指向的结点。调用者保证p是合法的。
//返回p指向结点后继结点的指针。
//若p指向链表最后一个结点,返回指向头结点的指针。
node* delete_node(List L, node* p);
//删除链表L中所有数据域等于x的结点
void remove_node(List L, dataType x);
//使链表L成为一个空链表
void make_empty(List L);
//销毁链表L
void destroy_list(List L);

裁判测试程序样例:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef int dataType;

typedef struct _node
{
    dataType data;
    struct _node *prev;//指向前驱的指针
    struct _node *next;//指向后继的指针
}node;

typedef node* List;

//创建一个空的循环链表,返回指向头节点的指针。
List create_list();
//用尾插法向链表L中插入数据域等于x的结点
void insert(List L, dataType x);
//如果链表为空,则返回true,否则返回false。
bool is_empty(List L);
//顺序遍历链表L。输出所有结点的数据域。如果链表为空则输出NULL
void traverse(List L);
//逆序遍历链表L。输出所有结点的数据域。如果链表为空则输出NULL
void traverse_back(List L);
//返回第1个指向数据域等于x的结点的指针。如果没有则返回NULL。
node* search(List L, dataType x);
//删除指针p指向的结点。调用者保证p是合法的。
//返回p指向结点后继结点的指针。
//若p指向链表最后一个结点,返回指向头结点的指针。
node* delete_node(List L, node* p);
//删除链表L中所有数据域等于x的结点
void remove_node(List L, dataType x);
//使链表L成为一个空链表
void make_empty(List L);
//销毁链表L
void destroy_list(List L);

int main()
{
    int x;
    List mylist = create_list();
    //输入一系列正整数,输入0表示输入结束
    //用尾插法插入链表
    scanf("%d", &x);
    while (x != 0)
    {
        insert(mylist, x);
        scanf("%d", &x);
    }
    //顺序遍历链表
    traverse(mylist);
    //逆序遍历链表
    traverse_back(mylist);
    //输入要删除的结点数据域
    scanf("%d", &x);
    node *p = search(mylist, x);
    if (p != NULL)
    {
        delete_node(mylist, p);
    }
    //顺序遍历链表
    traverse(mylist);
    //逆序遍历链表
    traverse_back(mylist);
    //输入要删除的结点数据域
    scanf("%d", &x);
    remove_node(mylist, x);
    //顺序遍历链表
    traverse(mylist);
    //逆序遍历链表
    traverse_back(mylist);
    //销毁链表
    destroy_list(mylist);
    return 0;
}

/* 请在这里填写答案 */

输入样例:

在这里给出一组输入。例如:

10 20 10 10 20 30 0
20
10

输出样例:

在这里给出相应的输出。例如:

10 20 10 10 20 30 
30 20 10 10 20 10 
10 10 10 20 30 
30 20 10 10 10 
20 30 
30 20 

输入输出样例解释:

程序首先创建一个空的双向循环链表,如下图所示:

捕获3.PNG

输入的第1行是

10 20 10 10 20 30 0

此时程序创建一个带头节点的双向循环链表,如下图所示:

捕获.PNG


此时顺序输出

10 20 10 10 20 30

逆序输出

30 20 10 10 20 10

输入的第2行是

20

此时程序删除从头结点向后的第1个数据域等于20的结点,所以链表如下图所示:

捕获1.PNG


此时顺序输出

10 10 10 20 30

逆序输出

30 20 10 10 10

输入的第3行是

10

此时程序删除链表中所有数据域等于10的结点,所以链表如下图所示:

捕获2.PNG

此时顺序输出

20 30

逆序输出

30 20

代码长度限制

16 KB

时间限制

2500 ms

内存限制

128 MB

C程序如下:

List create_list() {
    List newnode = (List)malloc(sizeof(node));
    if (newnode == NULL) {
        exit(EXIT_FAILURE);
    }
    newnode->next = newnode;//头结点的next域指向自己
    newnode->prev = newnode;//头结点的prev域指向自己
    return newnode;//返回该头结点
}
void insert(List L, dataType x) {
    List p;
    p = (List)malloc(sizeof(node));//向内存申请一片空间
    p->data = x;//给新链表的数据域赋值
    List pTail = L->prev;//定义一个指针指向链表的尾巴
    p->prev = pTail;//让新的链表与原链表的尾结点链接
    pTail->next = p;
    p->next = L;//让新结点与原链表的头结点链接
    L->prev = p;
}
bool is_empty(List L) {
    List p = L;//定义一个指针p指向该链表的头结点
    if (p->next == L && p->prev == L) {
        return true;//如果该链表的next域和prev域都指向该链表的头结点
    }//则说明该链表为空返回true
    else {
        return false;//否则不为空返回false
    }
}
void traverse(List L) {
    List p = L;
    if (is_empty(p)) {
        printf("NULL");
    }
    p = L->next;//定义一个指针p指向第一个数据域
    while (p != L) {//顺序遍历这个单链表
        printf("%d ", p->data);//输出单链表中每个数据的值
        p = p->next;//p指针向后移动到下一个结点
    }
    printf("\n");
}
void traverse_back(List L) {
    List p = L;
    if (is_empty(p)) {
        printf("NULL");
    }
    p = L->prev;//定义一个指针p指向L链表的最后一个数据域
    while (p != L) {//逆序遍历这个单链表
        printf("%d ", p->data);//输出每一个结点的数据域
        p = p->prev;//p指针指向该结点的前一个结点
    }
    printf("\n");
}
node* search(List L, dataType x) {
    List p = L;//定义一个指针指向该单链表的头结点
    if (is_empty(p)) {//如果该链表为空
        return NULL;//返回NULL
    }
    p = L->next;//否则p指向单链表的第一个数据域
    while (p->data != x)//遍历这个单链表直到找到对应的数据
    {
        p = p->next;
        if (p == L) {
            return NULL;//如果遍历完没找到则返回NULL
        }
    }
    return p;//找到后返回该指针
}
node* delete_node(List L, node* p) {
    List q = L ->next;//定义一个指针指向单链表的第一个数据域
    while (q != p) {//遍历这个单链表直到找到对应指针所指向的结点
        q = q->next;
    }
    q->prev->next = q->next;//让需要删除结点的前一个结点与需要删除结点的后一个结点连接
    q->next->prev = q->prev;
    free(q);//释放需要删除结点的空间
}
void remove_node(List L, dataType x) {
    List pHead, q, pFree;//定义三个指针
    pHead = L;//pHead保存头指针的地址
    pFree = L->next;//用于删除的指针指向单链表的第一个数据域
    q = pFree->next;//q指针指向pFree指针的下一个结点
    while (pFree != pHead) {//遍历单链表
        if (pFree->data == x) {//找到要删除的结点
            pFree->prev->next = pFree->next;//让要删除结点的前一个结点与后一个结点链接
            pFree->next->prev = pFree->prev;//后一个结点即q指针所指向的结点
            free(pFree);//释放需要删除的结点
        }
        pFree = q;//pFree指向下一个结点
        q = pFree->next;//q继续向后指
    }
}
void make_empty(List L) {
    List p, q;
    p = L;//定义一个指针p指向链表的头结点
    q = L->next;//q指向链表的第一个数据域
    while (q != L)//遍历整个链表
    {
        p->next = q->next;//让头结点与要释放的结点的下一个结点链接
        q->next->prev = p;
        free(q);//释放该节点
        q = p->next;//指向下一个需要释放的结点
    }
}
void destroy_list(List L) {
    List p, q;
    p = L;//定义一个指针p指向链表的头结点
    q = p->next;//q指向链表的第一个数据域
    while (q != L)//遍历整个链表
    {
        p->next = q->next;//让头结点与要释放的结点的下一个结点链接
        q->next->prev = p;
        free(q);//释放该节点
        q = p->next;//指向下一个需要释放的结点
    }
    free(p);//释放头结点
}

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

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

相关文章

Windows安装MongoDB结合内网穿透轻松实现公网访问本地数据库

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

PandasAI的应用与实战解析(二):PandasAI使用流程与功能介绍

文章目录 1.使用PandasAI进行开发的流程2.配置文件解析3.支持的数据库类型4.支持的LLMs5.其他 PandasAI这个工具最突出的优点就是通过结合了Pandas和生成式LLMs&#xff0c;极大地为开发人员降低了工作量。 传统的开发调用流程&#xff08;数据分析相关&#xff09;&#xff1a…

秒杀购物商城核心服务 — 商品管理中心(前提设计概要)

秒杀购物商城核心服务 前提介绍商品中心中台支持系统-总体架构设计&#xff1a;商品与产品商品 类目属性类目定义前后台类目后台类目&#xff0c;关注标准化管理类目属性及分类 SKUSPU 属性库建设 前提介绍 在电商系统中&#xff0c;商品模型占据着举足轻重的地位&#xff0c…

AI赋能档案开放审核:实战

关注我们 - 数字罗塞塔计划 - 为进一步推进档案开放审核工作提质增效&#xff0c;结合近几年的业务探索、研究及项目实践&#xff0c;形成了一套较为成熟、高效的AI辅助档案开放审核解决方案&#xff0c;即以“AI人工”的人机协同模式引领档案开放审机制创新&#xff0c;在档…

TyG新文章!与胸痛的高发生率正相关 | NHANES数据库周报(4.10)

NHANES挖掘培训班来啦&#xff0c;就在4.20-21&#xff01; 郑老师团队2024年NHANES公共数据库挖掘培训班&#xff0c;由浅入深&#xff0c;零基础可学&#xff0c;欢迎报名&#xff01; 美国国家健康和营养检查调查&#xff08;NHANES&#xff09;是一项旨在评估美国成人和儿童…

Python通过socket搭建一个web服务器

目录 01、源码 02、运行结果 03、小结 Socket是一种计算机网络通信的一种机制&#xff0c;它允许不同计算机或进程之间通过网络进行数据传输和通信。Socket可以被看作是不同计算机之间的数据传输通道&#xff0c;通过这个通道&#xff0c;计算机之间可以进行双向的数据传输。…

区块链游戏:探索未来的可能性与挑战

区块链游戏是一种将区块链技术应用于游戏领域的创新产品&#xff0c;它为游戏行业带来了全新的模式和可能性。本文将深入探讨区块链游戏的优点、挑战和未来趋势&#xff0c;帮助读者了解这一新兴领域。 一、区块链游戏的优点 1. 公平性&#xff1a;区块链技术保证了游戏中的物…

LeetCode-Java:303、304区域检索(前缀和)

文章目录 题目303、区域和检索&#xff08;数组不可变&#xff09;304、二维区域和检索&#xff08;矩阵不可变&#xff09; 解①303&#xff0c;一维前缀和②304&#xff0c;二维前缀和 算法前缀和一维前缀和二维前缀和 题目 303、区域和检索&#xff08;数组不可变&#xff…

二叉树遍历算法和应用

二叉树是指度为 2 的树。它是一种最简单却又最重要的树&#xff0c;在计算机领域中有这广泛的应用。 二叉树的递归定义如下&#xff1a;二叉树是一棵空树&#xff0c;或者一棵由一个根节点和两棵互不相交的分别称为根节点的左子树和右子树所组成的非空树&#xff0c;左子树和右…

【数据结构】07查找

查找 1. 基本概念2. 顺序表查找2.1 顺序查找2.2 顺序查找优化-哨兵 3. 有序表查找3.1 折半查找&#xff08;二分查找&#xff09; 4. 分块查找&#xff08;索引顺序查找&#xff09;5. Hash表&#xff08;散列表&#xff09;5.1 散列函数的设计5.2 代码实现5.2.1 初始化Hash表5…

再谈C语言——理解指针(一)

内存和地址 内存 在讲内存和地址之前&#xff0c;我们想有个⽣活中的案例&#xff1a; 假设有⼀栋宿舍楼&#xff0c;把你放在楼⾥&#xff0c;楼上有100个房间&#xff0c;但是房间没有编号&#xff0c;你的⼀个朋友来找你玩&#xff0c; 如果想找到你&#xff0c;就得挨个房…

【C++11】异常知多少

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;熟练掌握C11异常 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安! > 专栏选自&#xff1a;C嘎嘎进阶 &g…

Ubuntu22.04 + ROS2 Humble的环境配置

Ubuntu22.04 ROS2 Humble的环境配置 文章目录 Ubuntu22.04 ROS2 Humble的环境配置(1) Set locale(2) Setup Sources(3)安装ROS2(4)检查是否成功安装 参考官方网站ROS2-Installation ROS2的各种版本及维护计划&#xff0c;可以参考ROS2-List of Distributions (1) Set locale…

gitlab、jenkins安装及使用文档二

安装 jenkins IP地址操作系统服务版本192.168.75.137Rocky9.2jenkins 2.450-1.1 jdk 11.0.22 git 2.39.3192.168.75.138Rocky9.2gitlab-ce 16.10.0 结合上文 jenkins安装 前期准备&#xff1a; yum install -y epel-release yum -y install net-tools vim lrzsz wget…

AIGC的崛起:定义未来内容创作的新纪元

&#x1f31f;文章目录 &#x1f31f;AIGC简介&#x1f31f; AIGC的相关技术与特点&#x1f31f;AIGC有哪些应用场景&#xff1f;&#x1f31f;AIGC对其他行业影响&#x1f31f;面临的挑战与问题&#x1f31f;AIGC未来发展 &#x1f31f;AIGC十大热门网站推荐&#xff1a; 文心…

一键开启Scrum回顾会议的精彩时刻

其实回顾会议作为一个检视、反馈、改进环节&#xff0c;不仅在传统的瀑布管理模式中&#xff0c;还是在Scrum一类的敏捷管理流程中&#xff0c;都是非常重要的活动。一些团队认为它无法产生直接的价值&#xff0c;所以有意忽略了这个会议&#xff1b;一些团队在越来越多的回顾中…

【Python】面向对象(专版提升2)

面向对象 1. 概述1.1面向过程1.2 面向对象 2. 类和对象2.1 语法2.1.1 定义类2.1.2 实例化对象 2.2 实例成员2.2.1 实例变量2.2.2 实例方法2.2.3 跨类调用 3. 三大特征3.1 封装3.1.1 数据角度3.1.2 行为角度3.1.3 案例:信息管理系统3.1.3.1 需求3.1.3.2 分析3.1.3.3 设计 3.2 继…

MySQL·:执行一条查询语句期间发生了什么?

MySQL的架构分为两层&#xff0c;Server 层和存储引擎层 server层负责建立连接、分析和执行SQL&#xff0c;MySQL&#xff0c;MySQL大多数的核心功能模块都在在这里实现&#xff0c;下图上半部分都是server层做的事情&#xff0c;另外&#xff0c;所有的内置函数&#xff08;如…

Springboot+Vue项目-基于Java+MySQL的房产销售系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

JS - BOM(浏览器对象模型)

BOM 浏览器对象模型 BOM可以使我们通过JS来操作浏览器 在BOM中为我们提供了一组对象&#xff0c;用来完成对浏览器的操作 BOM对象 BOM&#xff08;Browser Object Model&#xff09;是指浏览器对象模型&#xff0c;它提供了与浏览器窗口进行交互的对象和方法。BOM包括一些核…