1. 程式人生 > >堆排序查詢前N個最大數和二分查詢演算法

堆排序查詢前N個最大數和二分查詢演算法

先了解堆排序概念:堆排序利用了大根堆(或小根堆)堆頂記錄的關鍵字最大(或最小)這一特徵,使得在當前無序區中選取最大(或最小)關鍵字的記錄變得簡單。

(1)用大根堆排序的基本思想

① 先將初始檔案R[1..n]建成一個大根堆,此堆為初始的無序區

② 再將關鍵字最大的記錄R[1](即堆頂)和無序區的最後一個記錄R[n]交換,由此得到新的無序區R[1..n-1]和有序區R[n],且滿足R[1..n-1].keys≤R[n].key

③由於交換後新的根R[1]可能違反堆性質,故應將當前無序區R[1..n-1]調整為堆。然後再次將R[1..n-1]中關鍵字最大的記錄R[1]和該區間的最後一個記錄R[n-1]交換,由此得到新的無序區R[1..n-2]和有序區R[n-1..n],且仍滿足關係R[1..n-2].keys≤R[n-1..n].keys,同樣要將R[1..n-2]調整為堆。

……

直到無序區只有一個元素為止。

(2)大根堆排序演算法的基本操作:

① 初始化操作:將R[1..n]構造為初始堆;

② 每一趟排序的基本操作:將當前無序區的堆頂記錄R[1]和該區間的最後一個記錄交換,然後將新的無序區調整為堆(亦稱重建堆)。

時間複雜度O(N*logN)

#include <iostream>
#include <string>
#include <vector>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

using namespace std;

//建立大根堆,即父節點大於兩個子節點
void MaxHeapCreate(int array[],int n,int length) {
int temp;
int maxChild;
for(temp = array[n]; 2*n+1 < length ; n = maxChild) {
maxChild = 2*n+1;
if(maxChild<length-1 && array[maxChild+1]>array[maxChild] )
maxChild++;
if( temp < array[maxChild] ) {
array[n] = array[maxChild];
array[maxChild] = temp;
} else {
break;
}
}
}

void HeapSort(int array[],int length) {
int temp;
int i;
//由底下第一個非葉子節點開始逐個往上建立大根堆,使每個節點滿足大根堆
//精髓部分,這步保證堆頂為最大
for( i = length/2 -1 ; i >= 0; i--) {
MaxHeapCreate(array,i,length);
}
for( i = length-1; i > 0 ; i-- ) {
temp = array[0];
array[0] = array[i];
array[i] = temp;
MaxHeapCreate(array,0,i);
}

}

void findFirstN(int array[],int length,int result[],int n) {
int temp;
int i,j;
for( i = length/2-1 ; i>=0 ; i-- ) {
MaxHeapCreate(array,i,length);
}
for( i = length-1,j=0; j<n && i > 0 ; i--) {
result[j++] = array[0];
temp = array[0];
array[0] = array[i];
array[i] = temp;
MaxHeapCreate(array,0,i);
}
}

template<typename T>
int BinSearch(T array[],int length,T key) {
int low = 0;
int high = length - 1;
int mid=0;
if(array[low] == key)
return low;
if(array[high] == key)
return high;
while(low<=high) {
mid = low + ((high-low)/2);
if( array[mid] == key ) {
return mid;
} else if( array[mid] > key ) {
high = mid - 1;
} else
low = mid + 1;
}
if(low>high)
return -1;
}

int main()
{
 
printf("-=-=-=-=-=堆排序=-=-=-=-=-=-=-=-=-=-=\n");
int array[]={12,15,8,33,96,76,38,22,9,23};
int a_length = sizeof(array)/sizeof(int);
HeapSort(array,a_length);

while(a_length--)
printf("array[%d]=%d\n",a_length,array[a_length]);
printf("-=-=-=-=-=利用堆排序查詢前n個最大元素=-=-=-=-=-=-=-=-=-=-=\n");
int array2[]={12,15,8,33,96,76,38,22,9,23};
int a2_length = sizeof(array2)/sizeof(int);
int nn=3;
int result[3];
findFirstN(array2,a2_length,result,3);
for(a2_length=0;a2_length<nn;a2_length++)
printf("result[%d]=%d\n",a2_length,result[a2_length]);
printf("-=-=-=-=-=二分查詢=-=-=-=-=-=-=-=-=-=-=\n");
printf("38的位置為:%d\n",BinSearch(array2,sizeof(array2)/sizeof(int),38));

return 0;
}