栈、队列、堆

第四章、栈和队列、堆

4.1、栈和队列的定义和特点

1、栈和队列是两种常用的、重要的数据结构

2、栈和队列是限定插入和删除只能在表的“端点”进行的线性表

3、栈和队列是线性表的子集合(是插入和删除位置受限的线性表)

4.1.1、栈(stack)定义和特点

1、栈:特殊的线性表,是限定仅在一端(通常是表尾)进行插入和删除操作的线性表

2、又称为后进先出的线性表,简称LIFO

3、相关概念

(1)栈是在表尾进行插入、删除操作的线性表

(2)表尾(an)称为栈顶(top),表头(a1)称为栈地Base

(3)插入栈顶(表尾),入栈

(4)栈顶(表尾)删除,出栈

(5)逻辑结构:和线性表一样,一对一关系

(6)存储结构:顺序或链式都可以,顺序更为常见

(7)运算规则:后进先出

4、入栈示意图


5、出栈示意图

image-20240414235638667

6、栈和一般线性表区别:仅在运算规则不同

4.1.2、队列的定义和特点

1、队列的定义:只能在表的一端进行插入运算,在另一端进行删除运算的线性表

2、特点:先进先出

3、逻辑结构:和线性表一样,一对一关系

4、存储结构:顺序或链式都可以,循环顺序更为常见

5、运算规则:队首和队尾运算,且先进先出原则

4.2、顺序表栈的表示和实现

4.2.1、顺序栈的初始化

1、定义数组

2、进行判断数组是否合法

3、栈顶和栈底相等,表示空

4、java代码实现

    private  int maxSize=100;//栈的最大值
    private int top=-1;//栈顶
    private int bottom = maxSize-1;
    private int [] stack;

    public Status_init(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[this.maxSize];
    }
    public Status_init(){
        stack = new int[maxSize];
    }

4.2.2、顺序栈是否为空/满

1、如果栈顶=栈底,则为空

2、java代码实现

//    判断栈是否空了
    public boolean isEmpty(){
        return top==-1;
    }
//    判断栈是否满了
    public boolean isFull(){
        return top == bottom;
    }

4.2.3、求顺序栈长度

1、栈顶-栈底

2、java代码实现

//    栈的长度
    public int statusLength(){
        return top+1;
    }

4.2.4、顺序栈入栈

1.判断是否栈满,满则错误

2、添加元素

3、栈顶++

4、java代码

//    入栈
    public void push(int value){
//        先判断是否为满
        if(isFull()){
            System.out.println("入栈失败,栈满咯");
        }else {
            top++;
            stack[top] = value;//入栈操作
            System.out.println(stack[top]+"入栈成功~~~");
        }
    }

4.2.5、顺序栈出栈

1、先判断是否为空,为空则错误

2、选取需要删除的元素

3、栈顶--

4、java代码实现

//    出栈
    public int pop(){
        if(isEmpty()){
            System.out.println("栈为空,无法出栈");
        }
        int value = stack[top];
        top--;
        System.out.println("出栈成功");
        return value;
    }

4.2.6、循环遍历栈

//    循环遍历栈
    public void outputStatus(){
        if(isEmpty()){
            System.out.println("栈为空,没有数据");
        }
        for(int i =top;i>=0;i--){
            System.out.println("stat[]=:"+stack[i]+"\t");
        }
    }

4.3、链式栈的表示和实现

4.3.1、链栈的表示

1、链栈是运算受限的单链表,只能在链表头部进行操作。

2、注意:链栈中指针的方向是指向链表前驱的。an—>an-1

(1)图示

image-20240414235825750

3、链表的头结点就是栈顶

4、不需要头结点

5、基本不存在栈满的情况

6、空栈下相当于指针指向空

7、插入和删除仅在栈顶处执行

4.3.2、链栈的初始化

2、JAVA代码实现

    //    定义栈顶和栈底元素
    private Element base;//栈底
    private Element top;//栈顶

    //链栈的数据模型
    class Element {
        public Object data;//存储数据
        Element next;//指针
    }
//    初始化栈
public void init() {
    Element elem = new Element();//初始化一个空间
    base = elem;
    top = elem;
    base.data = null;
    System.out.println("栈成功初始化");
}

4.3.3、链栈的入栈

1、相当于单链表的头插法

2、java代码实现

//    入栈操作
public void push(Object obj) {
    Element elem = new Element();
    elem.data = obj;
    elem.next = top;
    top = elem;//修改栈顶为入栈的元素
    System.out.println("链栈元素成功加入");
}

4.3.4、链栈的出栈

1、

2、java代码实现

//    退栈操作
public Object pops() {
    if (isEmpty()) {
        System.out.println("退栈失败,栈为空");
    }
    Object object = top.data;
    top = top.next;//修改指针
    System.out.println(object+"退栈成功");
    return object;
}

4.3.5、取出链栈顶/底的值

1、就是取出头结点的值

2、java代码实现

//    取出栈底的值
    public Element getBase() {
        return base;
    }
//    获取栈顶
    public Element getTop() {
        return top;
    }

4.3.6、遍历链栈

1、while判断,base==top//表示为空

2、java代码实现

//    遍历栈
    public void printLinkStatus(){
        if (isEmpty()) {
            System.out.println("栈为空");
        }
        Element temp = top;
        while (temp!=base){
            System.out.println("数据——》"+temp.data);
            temp = temp.next;
        }
    }

4.3.7、获取链栈大小

1、和遍历链栈相似

//    获取栈大小
    public String getSize(){
        int size = 0;
        Element temp = top;
        while (temp!=base){
            temp =temp.next;
            size++;
        }
        return "该栈大小为:"+size;
    }

4.4、栈与递归

4.4.1、递归的定义

1、若是对象部分地包含自己,或用它自己给自己定义,则称为递归。

2、一个过程直接或简介地调用自己也是递归。

4.4.2、递归常见用途

1、递归定义的数学函数

2、具有递归特性的数据结构

3、可递归求解问题

(1)分治法、迷宫问题、汉诺塔等

4、递归要使用的三个条件

(1)能将一个问题转变为一个新问题,而新问题与原问题的解法相同或类同,不同的仅是处理的对象,且这些处理对象是变化有规律的。

(2)可以通过上述转化而使问题简化。

(3)必须有一个明确的递归出口,或称递归的边界。

4.4.3、分治法求解递归问题算法一般格式

image-20240414235919558

4.4.4、函数调用过程(递归)

image-20240414235938350

4.4.5、例子

image-20240415000005079

4.4.6、递归函数调用的实现

image-20240415000015910

4.4.7、进行fact(4)调用的系统栈的变化状态

1、先进后出

2、递归到可以计算才能调回

4.4.8、递归的优缺点

1、优点

(1)结构清晰,程序易读

2、缺点

(1)每次调用要生成工作记录,保存状态信息,入栈;返回时要出栈,恢复状态信息,时间开销大。

4.4.9、递归—>非递归

1、方法一、尾递归、单向递归—>循环结构。

image-20240415000039285

2、借用栈模拟系统的运行栈

image-20240415000110006

4.5、顺序队列

4.5.1、相关术语

1、表头删除,表尾插入

2、a1表头,an表尾

3、先进先出的线性表

4、插入称为入队,删除称为出队

5、队列的存储结构为链队、或顺序队(常用循环顺序队)

4.5.2、队列的相关概念

image-20240415000154133

4.5.3、队列的常见应用

image-20240415000208037

4.5.4、队列的顺序表示—初始化

1、头指针==尾指针

2、图例

image-20240415000320231

3、java代码实现

   private int maxSize;//最大尺寸
    private int front;//头
    private int rear;//尾
    Object data [] ;//数组模拟队列
    public int count ;

//    初始化
    public arrqueue(int maxSize){
        if(maxSize<1){
            maxSize=1;
        }
        this.maxSize=maxSize;
        data = new Object[maxSize];
        front = 0;//第一个元素的
        rear  = 0;//最后一个元素
        count=0;
    }

4.5.5、队列的顺序表示—入队

1、尾指针++,头指针不变

2、数据放入数组中

3、图例

image-20240415000344893

4、java代码实现

//    加入数据
    public void addQueue( Object obj){
        if(isFull()){
            System.out.println("数据队列已满~");
        }
        rear++;
        data [rear] = obj;
        count++;
    }

4.5.6、队列的顺序表示—出队

1、头指针++

2、空队标志:front==rear

3、图例

image-20240415000358661

4、java代码实现

//    删除队列
    public void delQueue(){
        if(isEmpty()){
            System.out.println("队列为空~");
        }
        System.out.println(front+"删除成功");
        front++;
        count--;

    }

4.5.7、解决假上溢的方法

1、理解

image-20240415000456069

2、引入循环队列

(1)利用rear+1%MaxSize

4.5.8、循环队列—初始化

1、base、front、rear

2、java代码实现

public class CircularQueue {
    private int maxSize;//最大尺寸
    private int front;//头
    private int rear;//尾
    Object data [] ;//数组模拟队列

    //    初始化
    public CircularQueue(int maxSize) {
        this.maxSize=maxSize;
        data = new Object[maxSize];
        front = 0;//第一个元素的
        rear  = 0;//最后一个元素
        }

4.5.9、循环队列—插入

1、base[rear] = x; //x为插入的数据

2、rear = (rear+1)%MaxSize;

3、java代码实现

//    加入元素
    public void addCirQueue(Object objData){
        if(isFull()){
            System.out.println("队列已满,无法添加");
            return;
        }
        data[rear] = objData;
        rear = (rear+1)%maxSize;//修改队尾指针
    }

4.5.10、循环队列—删除元素

1、x=base[front]

2、front = (front+1)%MaxSize;

3、java代码实现

//  删除元素并返回被删除元素
    public Object delCirQueue(){
        if(isEmpty()){
            System.out.println("队列为空,无法删除");
            return 0;
        }
        Object reX = data[front];//返回被删除的元素名称
        front = (front+1)%maxSize;//重写判断front的位置
        return reX+"被成功删除了";
    }

4.5.11、循环队列—判断队空,队满。

1、当(rear+1)%MaxSize==front时,队列空/满

(1)就是尾指针向后移动一位正好是front

2、解决方案

image-20240415000524765

3、图解

image-20240415000538553

4、java代码实现

//        判断是否为满
    public boolean isFull(){
        if((rear+1)%maxSize==front){
            return true;
        }else {
            return false;
        }
    }
//        判断是否为满空
    public boolean isEmpty(){
        if(rear==front){//rear+1表示有一个空的作为分割
            return true;
        }else {
            return false;
        }
    }

4.5.12、循环队列—求队列的长度

1、理解

image-20240415000555437

2、java代码实现

//    求队列的长度
    public int getLength(){
        return (rear-front+maxSize)%maxSize;
    }

4.5.13、循环队列—取队头元素

1、判断是否为空

2、data[front]

//    去队头元素
    public Object getHead(){
        if(isEmpty()){
            System.out.println("队列为空,无数据");
            return 0;
        }
        return data[front];
    }

4.5.14、循环队列—遍历队列

1、(i+maxSize)%maxSize!=rear

2、java代码实现

//    循环遍历队列
    public void showCirQueue(){
        int i = front;
        while ((i+maxSize)%maxSize!=rear){
            System.out.println(data[i]);
            i++;
        }
    }

4.6、链式队列

4.6.1、链队列类型定义(数据模型)

1、有data变量

2、有next指针

3、图示

image-20240415000637102

4、java代码实现

public class LinkNode {
    Object object;
    LinkNode next;
    public LinkNode(Object object) {
        this.object = object;
    }
}

4.6.2、链队列—运算指针变化状况

image-20240415000648440

4.6.2、链队列—初始化

1、开辟元素空间

2、初始化头指针和尾指针

3、数据初始化

4、java代码实现

//  初始化
    LinkNode rear = null;
    LinkNode head = null;

4.6.3、链队列—销毁链队列

1、算法思路:从头结点开始,依次释放所有节点

2、利用循环

3、rear==front.next;

​ free(front);

​ front==rear;

4、java代码实现

4.6.4、链队列—入队列

1、利用尾插法

2、java代码实现

//    入队列
    public void addLinkQueue(Object object){
        LinkNode newNode = new LinkNode(object);
        if(rear==null){//如果尾指针为空,设置头指针和尾指针
            rear = newNode;
            head = newNode;
            return;
        }
        LinkNode temp = rear;
        while (temp.next!=null){
            temp = temp.next;
        }
        temp.next = newNode;//把新加入的元素放在最尾
        System.out.println("加入成功");
    }

4.6.5、链队列—删除队列元素

1、指针绕过要删除的节点,直接跳转到被删除的下一个节点

2、java代码实现

//    删除队列元素
    public boolean delLinkQueue(){
        if(head.next!=rear){//如果不为空
            head = head.next;//指针绕过要删除的节点,直接跳转到被删除的下一个节点
            System.out.println("删除成功");
            return true;
        }
        return false;
    }

4.6.6、取出队列首/尾元素

1、有瑕疵

2、java代码实现

/    取出队列首值
    public void getHead(){
        if(isEmpty()){
            System.out.println("队列为空");

        }else {
            System.out.println("队列首值为"+head.next.object);
        }
    }
//    取队列尾值
    public void getRear(){
        LinkNode temp = rear;//中间指针
        while (temp.next!=null){//temp如果不是最后一个
            temp = temp.next;
        }
        if(isEmpty()){
            System.out.println("队列为空");
        }else {
            System.out.println("队尾的值是:"+temp.object);
        }
    }

4.6.7、链队列—求队列的长度

1、利用while循环
2、java代码实现

//    求队列的长度
    public void Length(){
        LinkNode temp = head;
        int i=0;
        if(isEmpty()){
            System.out.println("队列为空");
        }else {
            while (temp.next!=null){
                i++;
                temp = temp.next;
            }
        }
        System.out.println("队列的长度为"+i);
    }

4.6.8、链队列—展示队列

1、利用循环

2、java代码实现

//    展示队列
    public void  showLinkQueue(){
        LinkNode temp = head;
        int i=0;
        if(isEmpty()){
            System.out.println("队列为空");
        }else {
            while (temp.next!=null){
                i++;
                temp = temp.next;
                System.out.println(temp.object);
            }
        }
    }

4.7、堆

image-20221115205405439

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇