作者: 雨落夏至 | 来源:发表于2019-11-14 19:32 被阅读0次

  • 线性数据结构,不是非线性
  • 用一维数组实现,本质为完全二叉树
遍历堆从根到叶结点
  • 先从右结点开始遍历


void dfs(int d)
{
    if(2 * d > n){ //不再往下搜索
        if(d <= n){
            for(int i = 0; i < path.size(); ++i){
                if(i != path.size() - 1)
                    printf("%d ",path[i]);
                else printf("%d\n",path[i]);
            }
        }
        return;
    }
    //先走右子树
    path.push_back(keys[2 * d + 1]);
    dfs(2 * d + 1);
    path.pop_back();//回溯
    //再走左子树
    path.push_back(keys[2 * d]);
    dfs(2 * d);
    path.pop_back();//回溯
}
判断最大堆最小堆
for(int i = 2; i <= n; ++i){
       if(keys[i / 2] > keys[i]) isMin = 0;
       if(keys[i / 2] < keys[i]) isMax = 0;
    }

堆排序

基本思想:

  • 首先将待排序的数组构造成一个大根堆,此时,整个数组的最大值就是堆结构的顶端
    每次新插入的数据都与其父结点进行比较,如果插入的数比父结点大,则与父结点交换,否则一直向上交换,直到小于等于父结点,或者来到了顶端

  • 将顶端的数与末尾的数交换,此时,末尾的数为最大值,剩余待排序数组个数为n-1
    将n次最末尾的数提出,即可得排好序的数组,利用最大堆顶端的数一定是数组中的最大值

  • 将剩余的n-1个数再构造成大根堆,再将顶端数与n-1位置的数交换,如此反复执行,便能得到有序数组
    此时最大数已经来到末尾,则固定不动/提出,后面只需要对顶端的数据进行操作即可,拿顶端的数与其左右孩子较大的数进行比较——如果顶端的数大于其左右孩子较大的数,则停止;如果顶端的数小于其左右孩子较大的数,则交换,然后继续与下面的孩子进行比较

以前老是以为要递归。。。。
嗷嗷嗷,静下心写写原始堆排序也挺简单的hhh(开始做梦,然后被吊打

#include<iostream>

using namespace std;
int n;

void swap(int a,int b,int heap[]){
    int temp;
    temp=heap[a];
    heap[a]=heap[b];
    heap[b]=temp;
}

void createHeap(int heap[],int size){
    int i=size;
    while(i/2>=1){
        if(heap[i/2]<heap[i]){
            swap(i/2,i,heap);
        }
        i=i/2;
    }
}

int main(){

    cin>>n;
    int heap[1001]={0};
    for(int i=1;i<=n;i++){
        cin>>heap[i];
        createHeap(heap,i);
    }
    for(int i=1;i<=n;i++){
        cout<<heap[i]<<" ";
    }
    cout<<endl;
    for(int i=n;i>=1;i--){
        swap(1,i,heap);
        cout<<heap[i]<<" ";
        int start=1;
        while(start*2<=i-1){
            if(heap[start]<heap[start*2]){
                if(start*2+1>i-1||heap[start*2]>heap[start*2+1]){
                    swap(start*2,start,heap);
                    start=start*2;

                }
                else{
                    swap(2*start+1,start,heap);
                    start=start*2+1;
                }
            }
            else{
                if(start*2+1<=i-1&&heap[start]<heap[start*2+1]){
                    swap(start*2+1,start,heap);
                    start=start*2+1;
                }
                else break;
            }
//            cout<<"+"<<heap[start]<<"--"<<start<<endl;
        }
    }
    return 0;
}

相关文章

  • 堆 - 堆的应用

    堆有三个典型的应用场景:实现优先队列、求 Top K 、求中位数 实现优先队列 优先队列:队列的性质是先进先出,但...

  • 二叉堆是一棵满二叉树,父节点的值大于子节点。 用数组存储二叉堆,假如一个节点的下标为k,那么这个节点的左孩子就是2...

  • 应用: 排序,从小到大用最大堆,从大到小用最小堆 选出元素中的 top k 个top k 个最小数:数组前k个元素...

  • 完全二叉树 二叉堆 二叉堆有最大堆和最小堆的区别,最大堆只保证每个节点的父节点大于当前节点,但不保证上一层节点的值...

  • 堆的定义: n个元素序列{k1,k2,...,ki,...,kn},当且仅当满足下列关系时称之为堆: (ki...

  • http://bubkoo.com/2014/01/14/sort-algorithm/heap-sort/ 1 ...

  • 堆 …

    南山南,北山北,南山有谷堆,北山有花蕾,山坡下,大道中,野树停在石堆,秋风送,冷雪飘,旅途空旷叶儿飞,时间漫,皱纹...

  • 题目:100w个数中找出最大的100个。 维护一个100个元素的小根堆即可。 或者直接维护一个用来存储当前最大的1...

网友评论

      本文标题:

      本文链接:https://www.haomeiwen.com/subject/yiccictx.html