秋招過了,春招還會遠麼?真實面試題:工做一年同事跳槽,去某爲,就考了一道:用數組實現堆排序,下面就來介紹一下堆排序的實現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; } };
直接上圖,再說明,以下圖:
代碼以下:
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++; }
直接上圖,以下:
代碼以下:
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(); }
運行結果以下:
就是用構造函數來實現最大堆,見下圖:
代碼以下:
//構造函數,經過給定數組實現最大堆 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
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; }
正如前面所說:秋招已過,春招還會遠麼?18年還有一個月就要結束了,感受比大學時過的時間還快!有個戰略要改變,以前定的年末以前一直要學數據結構和算法,這個計劃要伴隨整個職業生涯了,最起碼一直到明年5月,都要一直堅持學!