4/1--4/7最大堆 C++实现

news/2024/5/19 6:24:45 标签: 最大堆, 堆排序

 

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

template<typename T>
class maxHeap
{
private:
    T* data;  //保存元素的数组指针
    int sz;  //最大堆里的元素个数
    int cap;  //容量

    void shiftup(int k);   //将第k个元素向上调整
    void shiftdown(int k);  //将第k个元素向下调整


public:
    maxHeap(int n);  //构造函数
    maxHeap(const maxHeap& mh);  //拷贝构造函数


    maxHeap& operator=(const maxHeap& mh) ; //赋值构造函数


    maxHeap(T arr[],int n);  //从数组调整成堆


    int heapsize()const;

    int heapcap()const;

    bool heap_insert(T num);

    void print();

    T extractmax();
};

template<typename T>
void maxHeap<T>::shiftup(int k)  //将第k个元素向上调整
{
    while((k-1)/2>=0)  //还有父亲节点
    {
        if(data[k]<=data[(k-1)/2])  //已经到适合的位置
        {
            break;
        }
        else
        {
            swap(data[k],data[(k-1)/2]); //和父节点进行交换
            k=(k-1)/2;    //对新的父节点重复相同的操作
        }
    }
}

template<typename T>
maxHeap<T>::maxHeap(int n) //构造函数
{
    data=new T[n];  //开辟一个大小为n的数组空间
    sz=0;
    cap=n;
}

template<typename T>
maxHeap<T>::maxHeap(const maxHeap& mh)  //拷贝构造函数
{
    sz=mh.heapsize();
    cap=mh.heapcap();

    if(sz==0)
    {
        return;
    }
    data=new T[sz];
    for(int i=0; i<sz; i++)
    {
        data[i]=mh.data[i];
    }
}

template<typename T>
maxHeap<T>& maxHeap<T>:: operator=(const maxHeap& mh)  //赋值构造函数
{
    if(*this=mh)
    {
        return *this;
    }
    //释放原来的空间,重新分配空间进行存储
    delete[] data;
    sz=mh.heapsize();
    cap=mh.heapcap();
    if(cap==0)
    {
        return *this;
    }
    data=new T[cap];
    for(int i=0; i<sz; i++)
    {
        data[i]=mh.data[i];
    }
    return *this;
}

template<typename T>
maxHeap<T>::maxHeap(T arr[],int n)  //从数组调整成堆
{
    sz=n;
    cap=n;
    data=new T[n];
    for(int i=0; i<n; i++)
    {
        data[i]=arr[i];
    }
    for(int i=(n-2)/2; i>=0; i--)  //第一个非叶子节点为(n-2)/2
    {
        shiftdown(i);
    }
}

template<typename T>
int maxHeap<T>::heapsize()const
{
    return sz;
}
template<typename T>
int maxHeap<T>::heapcap()const
{
    return cap;
}
template<typename T>
bool maxHeap<T>::heap_insert(T num)
{
    if(sz>=cap)
    {
        return false;
    }
    data[sz]=num;
    sz++;
    shiftup(sz-1);
    return true;
}
template<typename T>
void maxHeap<T>:: print()
{
    for(int i=0; i<sz; i++)
    {
        cout<<data[i]<<" ";
    }
    cout<<endl;

}
template<typename T>
T maxHeap<T>:: extractmax()
{
    T temp=data[0];
    data[0]=data[sz-1];
    sz--;
    shiftdown(0);
    return temp;
}


template<typename T>
void maxHeap<T>::shiftdown(int k)  //将第k个元素向下调整
{
    while(2*k+1<sz)  //该节点有左孩子
    {
        int j=2*k+1;
        if(j+1<sz && data[j]<data[j+1])
        {
            j=j+1;
        }
        if(data[k]>=data[j])
        {
            break;
        }
        swap(data[k],data[j]);
        k=j;
    }
}

template<typename T>
void heapsort(T arr[],int n)   //将每个元素依次插入一个空堆中,算法复杂度为O(nlogn)
{
    maxHeap<T> mh=maxHeap<T>(n);
    for(int i=0; i<n; i++)
    {
        mh.heap_insert(arr[i]);
    }
    mh.print();
}

template<typename T>
void heapsort2(T arr[],int n)  //将一个数组调整成堆,算法复杂度为O(n)
{
    maxHeap<T> mh=maxHeap<T>(arr,n);
    mh.print();
}

int main()
{
    maxHeap<int> mp(100);
    srand(time(NULL));
    for(int i=0; i<15; i++)
    {
        mp.heap_insert(rand()%100);
    }
    mp.print();
    cout<<mp.extractmax()<<endl;
    mp.print();
    int a[15];
    for(int i=0;i<15;i++)
    {
        a[i]=rand()%100;
    }
    heapsort2<int>(a,15);


    return 0;
}

原地堆排序

void __shiftDown(int arr[],int n,int k)
{
    while(2*k+1<n)
    {
        int j=2*k+1;
        if(j+1<n && arr[j]<arr[j+1])
        {
            j++;
        }
        if(arr[k]>=arr[j])
            break;
        swap(arr[k],arr[j]);
        k=j;
    }
    return;
}

void heapSort(int arr[],int n)
{
    //heapify
    for(int i=(n-2)/2; i>=0; i--)
    {
        __shiftDown(arr,n,i);
    }
    for(int i=n-1;i>0;i--)
    {
        swap(arr[0],arr[i]);
        __shiftDown(arr,i,0);
    }
    return;
}

如有哪里不对,欢迎批评指正!


http://www.niftyadmin.cn/n/1032270.html

相关文章

6/1-6/6并查集实现

用来解决连接问题 版本1&#xff1a;查找O(1)&#xff0c;union O(N) &#xff08;只有一层&#xff09; #include <iostream> #include <bits/stdc.h> using namespace std;class unionfind{int* id; //表示数据的组int cnt; public:unionfind(int n){idnew…

Reactor和Proactor模式

主线程只负责监听文件描述符上是否有事件发生&#xff0c;有的话就将可读可写事件放入请求队列&#xff0c;交给工作线程去处理。除此之外&#xff0c;主线程不做任何实质性的工作。读写数据、接受新的连接、以及处理客户请求均在工作线程中完成。 Proactor模式将所有的I/O操作…

数据结构和算法之美

06链表上&#xff1a;如何实现LRU缓存淘汰算法&#xff1f; 1 链表vs数组&#xff1a; 二者的区别首先在插入删除和随机访问的时间复杂度&#xff1b; 数组简单易用&#xff0c;使用连续的空间&#xff0c;可以借助CPU的缓存机制&#xff0c;预读数组中的数据&#xff0c;访问…

Matlab遗传算法道路图像阈值分割(附上完整源码)

图像阈值分割是图像处理中常用的一种方法&#xff0c;用于将图像分割为不同的区域。本文介绍了遗传算法在道路图像阈值分割中的应用。首先&#xff0c;对图像进行预处理&#xff0c;包括图像的灰度化和噪声去除。然后&#xff0c;通过遗传算法优化阈值的选择&#xff0c;以得到…

valgrind内存检测

目录 示例1&#xff1a;检测非法访问和内存泄漏 示例2&#xff1a;检测未初始化的内存&#xff1a; 示例3&#xff1a;内存读写越界&#xff1a; 示例4&#xff1a;内存覆盖 示例5&#xff1a;动态内存管理错误 示例6&#xff1a;内存泄漏 示例1&#xff1a;检测非法访问…

C++ 生产者消费者 四种情况

生产者消费者问题是多线程并发中一个非常经典的问题&#xff0c;相信学过操作系统课程的同学都清楚这个问题的根源。本文将就四种情况分析并介绍生产者和消费者问题&#xff0c;它们分别是&#xff1a;单生产者-单消费者模型&#xff0c;单生产者-多消费者模型&#xff0c;多生…

2021FAST《SpanDB: A Fast, Cost-Effective LSM-tree Based KV Store on Hybrid Storage》

混合存储&#xff0c;偏向SSD&#xff0c;以后有时间再细看 题目&#xff1a;SpanDB:一种快速、低成本的基于lsm树的混合存储KV存储

2021FAST《Facebook‘s Tectonic Filesystem: Efficiency from Exascale》

题目&#xff1a;Facebook的构造文件系统:来自百亿亿次的效率