栈&队列&堆

栈:一种只能在一端进行插入和删除的特殊线性表,按照先进后出的方式组织数据,先进入的数据被压入栈底,最后的数据被压入栈顶,需要读取数据时从栈顶开始弹出数据

队列:一种只能在一端进行数据的插入及另一端进行数据的删除的特殊线性表,按照先进先出的方式组织数据

堆:N个元素{k1, k2, k3, k4, k5, k6 ... kn}组成的集合,若满足下列关系之一则可称之为堆:

  1. ki <= k2i 且 ki <= k2i+1, (i = 1, 2, 3 ... n/2)
  2. ki >= k2i 且 ki >= k2i+1, (i = 1, 2, 3 ... n/2)

小根堆的图示如下:

栈的简单实现:

// Author: Waihui Zheng
// 栈

#include <iostream>
#include <assert.h>

namespace my_space {

template <typename T>
class stack {
public:
    stack() : _top_index(0) {}
    ~stack() {}

    void push(const T& value) {
        assert(_top_index < MAXN);
        _array[_top_index++] = value;
    }

    void pop() {
        assert(_top_index > 0);
        --_top_index;
    }

    T& top() {
        assert(_top_index > 0);
        return _array[_top_index - 1];
    }

    const T& top() const {
        assert(_top_index > 0);
        return _array[_top_index - 1];
    }

    bool empty() const {
        return _top_index == 0;
    }

    bool full() const {
        return _top_index == MAXN;
    }

private:
    static const int MAXN = 1000;
    T _array[MAXN];
    int _top_index;
};

}

int main() {
    my_space::stack<int> st;
    st.push(7);
    st.push(8);
    st.push(9);

    while (!st.empty()) {
        std::cout << st.top() << " ";
        st.pop();
    }

    std::cout << std::endl;

    return 0;
}

队列的简单实现:

// Author: Waihui Zheng
// 队列

#include <iostream>
#include <assert.h>

namespace my_space {

template <typename T>
class queue {
public:
    queue() : _front_index(0), _last_index(0) {}
    ~queue() {}

    void push(const T& value) {
        assert(!full());
        _array[_front_index] = value;
        _front_index = (_front_index + 1) % MAXN;
    }

    void pop() {
        assert(!empty());
        _last_index = (_last_index + 1) % MAXN;
    }

    T& front() {
        assert(!empty());
        int index = _front_index - 1;
        if (index < 0) {
            index += MAXN;
        }

        return _array[index];
    }

    const T& front() const {
        assert(!empty());
        int index = _front_index - 1;
        if (index < 0) {
            index += MAXN;
        }

        return _array[index];
    }

    T& back() {
        assert(!empty());
        return _array[_last_index];
    }

    const T& back() const {
        assert(!empty());
        return _array[_last_index];
    }

    bool empty() const {
        return _front_index == _last_index;
    }

    bool full() const {
        return (_front_index + 1) % MAXN == _last_index;
    }

private:
    static const int MAXN = 1000;
    T _array[MAXN];
    int _front_index;   // 前方插入
    int _last_index;    // 后方删除
};

}

int main() {
    my_space::queue<int> q;
    q.push(7);
    q.push(8);
    q.push(9);

    while (!q.empty()) {
        std::cout << q.back() << " ";
        q.pop();
    }

    std::cout << std::endl;
    return 0;
}

堆的简单实现:

// Author: Waihui Zheng
// 堆
// N个元素{k1, k2, k3, k4, k5, k6 ... kn}组成的集合,若满足下列关系之一则可称之为堆
// 1. ki <= k2i 且 ki <= k2i+1, (i = 1, 2, 3 ... n/2)
// 2. ki >= k2i 且 ki >= k2i+1, (i = 1, 2, 3 ... n/2)

#include <iostream>
#include <algorithm>
#include <assert.h>

namespace my_space {

template <typename T>
class MaxHeap {
public:
    MaxHeap() : _length(0) {}
    ~MaxHeap() {}

    // 插入操作,则是将将元素追加于数据尾部,然后向上调堆
    void push(const T& value) {
        // 下标从1开始,最多只能存放MAXN - 1个元素
        assert(_length < MAXN - 1);
        _array[++_length] = value;
        adjust_heap_up(_array, _length);
    }

    // 堆的删除操作,则是将第一个元素删除,将最后一个元素放于第一个位置,然后向下调堆
    void pop() {
        assert(_length > 0);
        std::swap(_array[1], _array[_length]);

        --_length;
        if (_length <= 0) {
            return ;
        }

        adjust_heap_down(_array, 1, _length);
    }

    void print() {
        for (int i = 1; i <= _length; ++i) {
            std::cout << _array[i] << " ";
        }

        std::cout << std::endl;
    }

    // 便于理解,依然元素小标从1开始
    void heap_sort(T* array, int length) {
        for (int root = length / 2; root >= 1; --root) {
            adjust_heap_down(array, root, length);
        }

        for (int last_index = length; last_index > 1;) {
            std::swap(array[1], array[last_index]);

            --last_index;
            adjust_heap_down(array, 1, last_index);
        }
    }

private:
    // 向下调堆,用于删除操作
    void adjust_heap_down(T* data, int root_index, int last_index) {
        T temp = data[root_index];
        int cur_index = root_index * 2;
        while (cur_index <= last_index) {
            // 选取子节点键值最大的节点
            if (cur_index < last_index && data[cur_index + 1] > data[cur_index]) {
                ++cur_index;
            }

            // 若当前节点的键值 小于等于 父节点的键值,说明调堆成功并结束
            if (data[cur_index] <= temp) {
                break;
            }

            // 当前节点键值大于父节点,当前键值上移
            data[root_index] = data[cur_index];
            root_index = cur_index;
            cur_index = 2 * root_index;
        }

        data[root_index] = temp;
    }

    // 向上调堆,用于插入操作,元素下标从1开始
    void adjust_heap_up(T* data, int value_index) {
        T temp = data[value_index];
        for (int cur_index = value_index / 2; cur_index >= 1; value_index = cur_index, cur_index /= 2) {
            if (data[cur_index] >= temp) {
                break;
            }

            data[value_index] = data[cur_index];
        }

        data[value_index] = temp;
    }

private:
    static const int MAXN = 1000;
    T _array[MAXN];     // 为便于理解,数组第一个元素从下标1开始
    int _length;
};

}

int main() {
    my_space::MaxHeap<int> max_heap;

    int a[] = {88888, 3, 1, 5, 7, 10, 2};
    max_heap.heap_sort(a, sizeof(a) / sizeof(int) - 1);
    for (int i = 0; i < sizeof(a) / sizeof(int); ++i) {
        std::cout << a[i] << " ";
    }
    std::cout << std::endl;

    max_heap.push(5);
    max_heap.push(10);
    max_heap.push(13);
    max_heap.push(4);
    max_heap.push(18);

    max_heap.print();
    max_heap.pop();
    max_heap.print();
    return 0;
}
时间: 2024-08-24 01:50:21

栈&队列&堆的相关文章

理解 &quot;栈&quot; &quot;队列&quot;,&quot;堆&quot;(后进先出)

[栈] ??函数调用形成了一个栈帧 function foo(b) { var a = 10; return a + b + 11; } function bar(x) { var y = 3; return foo(x * y); } console.log(bar(7)); 当调用bar时,创建了第一个帧 ,帧中包含了bar的参数和局部变量.当bar调用foo时,第二个帧就被创建,并被压到第一个帧之上,帧中包含了foo的参数和局部变量.当foo返回时,最上层的帧就被弹出栈(剩下bar函数的调

【C/C++学院】0828-STL入门与简介/STL容器概念/容器迭代器仿函数算法STL概念例子/栈队列双端队列优先队列/数据结构堆的概念/红黑树容器

STL入门与简介 #include<iostream> #include <vector>//容器 #include<array>//数组 #include <algorithm>//算法 using namespace std; //实现一个类模板,专门实现打印的功能 template<class T> //类模板实现了方法 class myvectorprint { public: void operator ()(const T &

栈和队列的区别,栈和堆的区别

栈和队列的区别: 栈的插入和删除操作都是在一端进行的,而队列的操作却是在两端进行的. 栈是先进后出,队列是先进先出. 栈只允许在表尾一端进行插入和删除,队列只允许在表尾一端进行插入,在表头一端进行删除. 栈和堆的区别: 栈区:由编辑器自动分配释放,存放函数的参数值,局部变量的值等(基本类型值). 堆区:由程序员分配释放,若程序员不释放,程序结束时可能有OS回收(引用类型值). 栈(数据结构):一种先进后出的数据结构. 堆(数据结构):堆可以被看成是一棵树,如:堆排序. 原文地址:https://

前端进击的巨人(二):栈、堆、队列、内存空间

面试经常遇到的深浅拷贝,事件轮询,函数调用栈,闭包等容易出错的题目,究其原因,都是跟JavaScript基础知识不牢固有关,下层地基没打好,上层就是豆腐渣工程,新人小白,踏实踩土才是关键. 打地基第二篇:本篇我们将对JavaScript数据结构的知识点详解一二. JavaScript中有三种数据结构: 栈(stack) .堆(heap). 队列(queue). 栈(stack) 栈的特点是"LIFO,即后进先出(Last in, first out)".数据存储时只能从顶部逐个存入,取

数据结构学习笔记-排序/队/栈/链/堆/查找树/红黑树

排序: 插入排序:每次从剩余数据中选取一个最小的,插入已经排序完成的序列中 合并排序:将数据分成左右两组分别排序,然后合并,对每组数据的排序递归处理. 冒泡排序:重复交换两个相邻元素,从a[1]开始向a[0]方向冒泡,然后a[2]...当a[i]无法继续往前挤的时候说明前面的更小了,而且越往前越小(挤得越往前) 堆排序:构造最大堆,每次取走根结点(自然是最大的),再调用MAX-HEAPIFY算法(见后文的堆)恢复最大堆的性质,重复取走根结点 快速排序(对A[r]-A[n]进行排序): 1.从序列

.Net栈和堆详解

什么是栈堆 在计算机领域,堆栈是一个不容忽视的概念,栈堆是两种数据结构.堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除.要点:堆,队列优先,先进先出(FIFO—first in first out):栈,先进后出(FILO—First-In/Last-Out). 堆栈是一个在计算机科学中经常使用的抽象数据类型.堆栈中的物体具有一个特性: 最后一个放入堆栈中的物体总是被最先拿出来, 这个特性通常称为后进先出(LIFO)队列. 栈和堆的区别 堆栈空间分配

浅谈“栈和堆”

对于一些新人可能会不理解栈和堆是什么,在这里我简单介绍一下: 程序运行时,它的数据必须存储在内存中.一个数据项需要多大的内存.存储在什么地方.以及如何存储都依赖与该数据项的类型. 运行中的程序使用两个内存区域来存储数据:栈和堆. 首先,什么是“栈”? 栈是一个内存数组,是一个LIFO(last-in  first-out,后进先出)的数据结构.栈存储几种类型的数据: 某些类型变量的值 程序当前的执行环境 传递给方法的参数 栈的特征: 栈有如下几个普遍特征: 数据只能从栈的顶端插入和删除 把数据放

成员变量,局部变量,栈,堆的关系

变量主要有类变量.成员变量.局部变量三种. 变量主要有类变量.成员变量.局部变量三种. 类变量的的格式如下 class ClassA: static int age; 也就是说,类变量是定义在类中(而不是方法中)并且有static 修饰的变量. 成员变量的格式如下: class ClassB: int age; 也就是说,成员变量是定义在类中,但是没有static 修饰的变量. 局部变量呢,则是定义在方法中的(注意:JAVA中不怎么用函数这种说法的).比如最常见的. class ClassC:

JAVA中的栈和堆

JAVA在程序运行时,在内存中划分5片空间进行数据的存储.分别是:1:寄存器.2:本地方法区.3:方法区.4:栈.5:堆. 基本,栈stack和堆heap这两个概念很重要,不了解清楚,后面就不用学了. 以下是这几天栈和堆的学习记录和心得.得些记录下来.以后有学到新的,会慢慢补充. 一.先说一下最基本的要点 基本数据类型.局部变量都是存放在栈内存中的,用完就消失.new创建的实例化对象及数组,是存放在堆内存中的,用完之后不定期自动消除. 二.先明确以上两点,以下示例就比较好理解了 示例1 main