数据结构–不设头指针的循环链队列

本次数据结构的作业是设计一个只有尾指针的循环链队列,要求实现构造(有参 && 无参)、析构、出入列、获取头结点等功能。在完成过程中踩了很多坑(特别是在实现析构时qwq)

template
struct Node {
    DataType data;
    Node* next;
};

template
class LinkQueue {
    public:
     LinkQueue();
     LinkQueue(int [], int);
     ~LinkQueue();
     void EnQueue(DataType x);
     DataType DeQueue();
     DataType GetQueue();

    private:
     Node* rear;
};

有参构造&&无参构造

template
LinkQueue::LinkQueue(int arr[], int n) {
    rear = new Node;
    Node* p = rear;
    //储存首地址,最后把尾巴连上
    for(int i = 0; i < n; i++) {
        rear->next = new Node;
        rear = rear->next;
        rear->data = arr[i];
    }
    rear->next = p;
    // 把尾巴连到首部
}

template
LinkQueue::LinkQueue() {
    rear = NULL;
}

进队 && 出队

template
void LinkQueue::EnQueue(DataType x) {
    Node* p = new Node;
    p->data = x;
    if (rear == NULL) {
        rear = p;
        rear->next = p;
    } else {
        p->next = rear->next;  // 新建节点连接头指针
        rear->next = p; // 尾指针连接新节点
        rear = p; // 尾指针后移
    }
}

template
DataType LinkQueue::DeQueue() {
    Node* p = NULL;
    DataType x;
    if (rear == NULL)
        throw "dive dowm";
    p = rear->next;
    x = p->data;
    if (rear == p)
        rear = NULL;
    else
        rear->next = p->next;
    delete p;
    return x;
}

获取头结点

template
DataType LinkQueue::GetQueue() {
    if (rear != NULL)
        return rear->next->data;
        // return rear->data;
        // 这里rear已经指向队末,按照上一行代码,返回的是队末元素
    else
        throw "empty queue";
}

清空循环链队列(也可写成析构)

template
LinkQueue::~LinkQueue() {
    Node* p;
    while (rear != NULL) {
        // the wrong version:

        // p = rear;
        // rear = rear->next;
        // delete p;

        p = rear->next;
        if (rear == p) {
            delete rear;
            break;
        } else
            rear->next = p->next;
        delete p;
    }
}

关于这个析构函数,我在网上找了很多个版本,很多代码都是写成注释里的那样,包括老师给的答案也是,有些编译器直接运行可能看不出什么问题,但是放在debug模式里,就会报错

数据结构--不设头指针的循环链队列

如上图,在这里我已将循环链队列所有元素delete,当我查看变量的值时,发现,没那么简单,rear指针不为null,它指向的data值也是不规则的,也就不难说明为什么跳不出第46行的while循环了

数据结构--不设头指针的循环链队列

跳不出循环后,继续delete,就会报错,虽然提示 unKnown signal,实际上是队列为空,无法继续delete

那么怎么解决呢,我将出列函数改写,放到析构函数里,这样子在删除最后一个节点时就能跳出循环,结束析构

数据结构--不设头指针的循环链队列

完整代码

#include
using namespace std;

template
struct Node {
    DataType data;
    Node* next;
};

template
class LinkQueue {
   public:
    LinkQueue();
    LinkQueue(int[], int);
    ~LinkQueue();
    void EnQueue(DataType x);
    DataType DeQueue();
    DataType GetQueue();

   private:
    Node* rear;
};

template
LinkQueue::LinkQueue(int arr[], int n) {
    rear = new Node;
    // rear->data = arr[0];
    Node* p = rear;  // 储存首地址,最后把尾巴连接到首部
    for (int i = 0; i < n; i++) {
        rear->next = new Node;  // 不断开辟空间
        rear = rear->next;                // rear后移
        rear->data = arr[i];
    }
    rear->next = p;  //把尾巴连到首部
}

template
LinkQueue::LinkQueue() {
    rear = NULL;
}

template
LinkQueue::~LinkQueue() {
    Node* p;
    while (rear != NULL) {
        p = rear->next;
        if (rear == p) {
            delete rear;
            break;
        } else {
            rear->next = p->next;
        }
        delete p;
    }
}

template
void LinkQueue::EnQueue(DataType x) {
    Node* p = NULL;
    p = new Node;
    p->data = x;
    if (rear == NULL) {
        rear = p;
        rear->next = p;
    } else {
        p->next = rear->next;  // 新建节点连接头指针
        rear->next = p;        // 尾指针连接新节点
        rear = p;              // 尾指针后移
    }
}

template
DataType LinkQueue::DeQueue() {
    Node* p = NULL;
    DataType x;
    if (rear == NULL)
        throw "dive down";
    p = rear->next;
    x = p->data;
    if (rear == p)
        rear = NULL;
    else
        rear->next = p->next;
    delete p;
    return x;
}

template
DataType LinkQueue::GetQueue() {
    if (rear != NULL)
        return rear->next->data;
    // return rear->data;
    // 这里rear已指向队末,返回的是队末元素
    else
        throw "empty queue";
}

int main() {
    LinkQueue Queue;
    try {
        Queue.EnQueue(5);
        Queue.EnQueue(10);
        Queue.EnQueue(15);
        // Queue.EnQueue(20);
    } catch (char* wrong) {
        cout << wrong << endl;
    }
    cout << "get head element" << endl;
    cout << Queue.GetQueue() << endl;
    try {
        Queue.DeQueue();
    } catch (char* wrong) {
        cout << wrong << endl;
    }
    cout << "get head element" << endl;
    cout << Queue.GetQueue() << endl;
}

Original: https://www.cnblogs.com/jaydenchang/p/15455426.html
Author: JaydenChang
Title: 数据结构–不设头指针的循环链队列

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/585162/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • MyBatis 01 初始MyBatis

    实验五:初识Mybatis 实验目的: (1)考察知识点MyBatis入门程序 实验要求: 1)完成基于User表的查询、添加、更新和删除客户功能代码的编写,或者使用你自己项目中的…

    Java 2023年6月7日
    079
  • SSM整合(Spring+SpringMVC+Mybatis)

    IDEA创建一个webapp工程 选择骨架创建 1、Spring整合Mybatis 让Spring容器去管理 SqlSessionFactory对象 让Spring容器去创建并管理…

    Java 2023年6月8日
    072
  • HIT软构博客5–LAB2记录与总结

    本次实验我学习了ADT的设计、规约、测试,并使用OOP技术实现 ADT。 ​ 首先按照给定的需求,从中根据名词找到对应需要设计的ADT,然后确定ADT内所需要的方法,设计方法的sp…

    Java 2023年6月5日
    088
  • 给 Mac 添加右键菜单「使用 VSCode 打开」

    最终的实现效果是在文件 / 文件夹上右击时,会出现菜单项「用 VSCode 打开」,点击后会启动 Visual Studio Code 打开对应的文件 / 文件夹。 实现步骤 3….

    Java 2023年6月5日
    083
  • 接口和包–Java学习笔记

    interface定义:没有字段的抽象类 interface person{ void hello(); String getName(); } /*接口本质上就是抽象类 abst…

    Java 2023年6月8日
    093
  • Java开发笔记(一百三十九)JavaFX的输入框

    循着Swing的旧例,JavaFX仍然提供了三种文本输入框,分别是单行输入框TextField、密码输入框PasswordField、多行输入框TextArea。这些输入框都由抽象…

    Java 2023年6月6日
    098
  • TortoiseGit的使用

    简介 TortoiseGit是一款Git图形界面工具。 TortoiseGit的基本配置 安装好TortoiseGit后在任意目录下右击 汉化:前提安装中文包。note:下图中安装…

    Java 2023年6月15日
    058
  • 力扣刷题之路—–链表问题

    public ListNode mergeKLists(ListNode[] lists) { if(lists.length==0) return null; ListNode …

    Java 2023年6月5日
    0145
  • JAVA入门[23]-SpringBoot配置Swagger2

    一、新建SpringBoot站点1.新建module,然后引入pom依赖: 2.新建Controller文件 3.新建SpringBoot启动文件 4.运行,http://loca…

    Java 2023年5月29日
    087
  • OAuth2.0基本知识

    前置知识 关注客户端开发者的简易性 通过组织在资源拥有者和HTTP服务商之间的被批准的交互动作代表用户 允许第三方应用代表用户获得访问的权限 为Web应用、桌面应用、手机和起居室设…

    Java 2023年6月13日
    060
  • 和朱晔一起复习Java并发(五):并发容器和同步器

    和朱晔一起复习Java并发(五):并发容器和同步器 本节我们先会来复习一下java.util.concurrent下面的一些并发容器,然后再会来简单看一下各种同步器。 Concur…

    Java 2023年5月29日
    075
  • 【硬核】Dubbo常见面试题

    Dubbo 整体介绍的差不多了,今天就开始面试环节了,我会列举一些常见的 Dubbo 面试题,只会抓着重的,一些太简单的我就不提了。 不仅仅给你面试题的答案,也会剖析面试官问这个问…

    Java 2023年6月9日
    0112
  • 5.日期格式化

    例:”startTime”:{“date”:11,”hours”:0,”seconds&#822…

    Java 2023年6月13日
    089
  • for、foreach、stream 哪家的效率更高,你真的用对了吗?

    昨天在《SQL中那么多函数,Java8为什么还要提供重复的Stream方法,多此一举?》一文中,有同学指出Stream在数据量不庞大的情况,效率不如for循环。 这个就触及到我的知…

    Java 2023年5月29日
    0110
  • 设计模式——面向对象设计原则

    面向对象设计原则 都是为了高内聚低耦合原则。编程时基本都要遵守 分类原则:一种人只干一种事。 举例:(比较简单就不代码了) 人可以干的事情有很多:敲代码、唱歌、跳舞、打篮球&#82…

    Java 2023年6月14日
    053
  • 老徐和阿珍的故事:缓存穿透、缓存击穿、缓存雪崩、缓存热点,傻傻分不清楚

    人物背景:老徐,男,本名徐福贵,从事Java相关研发工作多年,职场老油条,摸鱼小能手,虽然岁数不大但长的比较着急,人称老徐。据说之前炒某币败光了所有家产,甚至现在还有欠债。阿珍,女…

    Java 2023年6月7日
    083
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球