秋招各大廠,必考的優先隊列和堆排序

  秋招過了,春招還會遠麼?真實面試題:工做一年同事跳槽,去某爲,就考了一道:用數組實現堆排序,下面就來介紹一下堆排序的實現python

 堆和優先隊列

  堆的定義 

n個元素的序列k={k0,k1,……,kn-1},當且僅知足條件ios

(1)ki >= k2i+1 和 ki >= k2i+2      (2)ki <= k2i+1 和 ki <= k2i+2面試

(1)稱爲大根堆 (2)稱爲小根堆算法

能夠把堆當作徹底二叉樹。編程

  優先隊列

優先隊列是一種常見的抽象數據類型,它與"隊列"不一樣,不遵循"先進先出"原則,而遵循"最大元素先出"原則,出隊和優先級有關。 api

優先隊列的基本操做有三個:數組

(1) 向優先隊列裏插入一個元素網絡

(2) 在優先隊列找出最大元素數據結構

(3) 刪除優先隊列中最大元素架構

能夠用堆來實現優先隊列

  二叉堆  

  最大堆定義

  堆中任一節點老是大於其父節點的值,堆老是一顆徹底二叉樹,本篇博客以實現最大堆爲主

  數組實現二叉堆

  用二叉樹來實現堆,是比較好的,也能夠用二叉樹的左右指針來實現,但這種太麻煩;由於是徹底二叉樹,因此也能夠用數組來實現二叉堆,見下圖:  PS:依舊是全博客園最醜圖

  

   

    

   說明:將數組的值來抽象成二叉樹,二叉樹圖上的紅色字就表示數組的下標,並且還能總結出藍色字體的規律。

  構建一個堆類,代碼以下:

  

template<typename Item>
class MaxHeap{
private:
    Item *data;    //數組
    int count;    //堆的大小
    int capacity;    //堆的容量
public:
    //構造函數 構建一個空堆
    MaxHeap(int capacity){

        data = new Item[capacity+1];
        count = 0;
        this->capacity = capacity;
    }
};

  

  最大堆的實現

  最大堆上插入元素 shift up

  直接上圖,再說明,以下圖:

  

  代碼以下:

  

 void shiftUp(int k){
        while(k>1 && data[k/2]<data[k]){
            swap(data[k/2],data[k]);
            k /= 2;
        }
    }

//向最大堆中插入元素
    void insert(Item item){
        assert(count+1<=capacity);
        data[count+1] = item;
        shiftUp(count+1);
        count++;
    }

  

  最大堆上取出元素 shift down

  直接上圖,以下:

  代碼以下:

  

void shiftDown(int k){
        while(2*k<=count){
            int j = 2*k;
            if(j+1<count && data[j+1]>data[j]) j++; //右孩子比左孩子,j移動
            if(data[k]>data[j]) break;
            swap(data[k],data[j]);
            k=j;
        }
    }

//從最大堆中取出堆頂元素
    Item extracMax(){
        assert(count > 0);
        Item ret = data[1];
        swap(data[1],data[count]);
        count--;
        shiftDown(1);
        return ret;
    }

  實現堆排序

  有了插入和取出,就能夠實現堆排序了,代碼以下:

  

//將全部元素插入堆,再取出
template<typename T>
void heapSort1(T arr[],int n){

    MaxHeap<T> maxheap = MaxHeap<T>(n); 
    for(int i=0;i<n;i++)
        maxheap.insert(arr[i]);

    //從小到大排序
    for(int i=n-1;i>=0;i--)
        arr[i] = maxheap.extracMax();

}

  運行結果以下:

  

  

  heapify實現最大堆

  構造函數實現heapify過程  

就是用構造函數來實現最大堆,見下圖:

 

  

 

  代碼以下:

//構造函數,經過給定數組實現最大堆 O(n)
    MaxHeap(Item arr[],int n){
        
        data = new Item[n+1];
        capacity = n;

        for(int i=0;i<n;i++)
            data[i+1] = arr[i];
        count = n;

        for(int i=count/2;i>=1;i--)
            shiftDown(i);
    }

// heapSort2, 藉助咱們的heapify過程建立堆
// 此時, 建立堆的過程時間複雜度爲O(n), 將全部元素依次從堆中取出來, 實踐複雜度爲O(nlogn)
// 堆排序的整體時間複雜度依然是O(nlogn), 可是比上述heapSort1性能更優, 由於建立堆的性能更優
template<typename T>
void heapSort2(T arr[], int n){

    MaxHeap<T> maxheap = MaxHeap<T>(arr,n);
    for( int i = n-1 ; i >= 0 ; i-- )
        arr[i] = maxheap.extracMax();

}

  

  整體代碼

  Heap.h頭文件,代碼以下:

  

#ifndef HEAP_H_
#define HEAP_H_

#include<algorithm>
#include<cassert>
using namespace std;

template<typename Item>
class MaxHeap{
private:
    Item *data;    //數組
    int count;    //堆的大小
    int capacity;    //堆的容量

    void shiftUp(int k){
        while(k>1 && data[k/2]<data[k]){
            swap(data[k/2],data[k]);
            k /= 2;
        }
    }

    void shiftDown(int k){
        while(2*k<=count){
            int j = 2*k;
            if(j+1<count && data[j+1]>data[j]) j++; //右孩子比左孩子,j移動
            if(data[k]>data[j]) break;
            swap(data[k],data[j]);
            k=j;
        }
    }
public:
    //構造函數 構建一個空堆
    MaxHeap(int capacity){

        data = new Item[capacity+1];
        count = 0;
        this->capacity = capacity;
    }

    //構造函數,經過給定數組實現最大堆 O(n)
    MaxHeap(Item arr[],int n){
        
        data = new Item[n+1];
        capacity = n;

        for(int i=0;i<n;i++)
            data[i+1] = arr[i];
        count = n;

        for(int i=count/2;i>=1;i--)
            shiftDown(i);
    }

    ~MaxHeap(){
        delete[] data;
    }

    //返回堆中的元素個數
    int size(){
        return count;
    }

    //判斷是否爲空
    bool isEmpty(){
        return count==0;
    }

    //向最大堆中插入元素
    void insert(Item item){
        assert(count+1<=capacity);
        data[count+1] = item;
        shiftUp(count+1);
        count++;
    }

    //從最大堆中取出堆頂元素
    Item extracMax(){
        assert(count > 0);
        Item ret = data[1];
        swap(data[1],data[count]);
        count--;
        shiftDown(1);
        return ret;
    }

};

#endif
View Code

  heap.cpp以下:

  

#include<iostream>
#include<algorithm>
#include"Heap.h"
#include "SortTestHelper.h"

//將全部元素插入堆,再取出
template<typename T>
void heapSort1(T arr[],int n){

    MaxHeap<T> maxheap = MaxHeap<T>(n); 
    for(int i=0;i<n;i++)
        maxheap.insert(arr[i]);

    //從小到大排序
    for(int i=n-1;i>=0;i--)
        arr[i] = maxheap.extracMax();

}


// heapSort2, 藉助咱們的heapify過程建立堆
// 此時, 建立堆的過程時間複雜度爲O(n), 將全部元素依次從堆中取出來, 實踐複雜度爲O(nlogn)
// 堆排序的整體時間複雜度依然是O(nlogn), 可是比上述heapSort1性能更優, 由於建立堆的性能更優
template<typename T>
void heapSort2(T arr[], int n){

    MaxHeap<T> maxheap = MaxHeap<T>(arr,n);
    for( int i = n-1 ; i >= 0 ; i-- )
        arr[i] = maxheap.extracMax();

}

int main(){
    
    int n = 10;
    
    
    // 測試1 通常性測試
    //cout<<"Test for random array, size = "<<n<<", random range [0, "<<n<<"]"<<endl;
    int* arr1 = SortTestHelper::generateRandomArray(n,0,n);
    int* arr2 = SortTestHelper::copyIntArray(arr1, n);
        
    SortTestHelper::testSort("Heap Sort 1", heapSort1, arr1, n);
    SortTestHelper::testSort("Heap Sort 2", heapSort2, arr2, n);
    
    for(int i=0;i<n;i++)
        cout << arr1[i] << " ";
    cout << endl;
    
    for(int i=0;i<n;i++)
        cout << arr2[i] << " ";
    cout << endl;

    delete[] arr1;
    delete[] arr2;
    cout <<endl;
}
View Code

  

  十一月總結

  正如前面所說:秋招已過,春招還會遠麼?18年還有一個月就要結束了,感受比大學時過的時間還快!有個戰略要改變,以前定的年末以前一直要學數據結構和算法,這個計劃要伴隨整個職業生涯了,最起碼一直到明年5月,都要一直堅持學!

  11月主要完成的

  •   學了python
  •         數據結構和算法完成了總體架構的學習和整理
  •         複習C++和操做系統

  12月計劃

  •   最主要的計劃就是有效深刻的學習數據結構和算法
  •        鞏固C++、操做系統和網絡編程

  

  2018年最後一個月了,你們加油!

相關文章
相關標籤/搜索