今天看《算法导论》学了堆排序,试下改用堆排序来写 复杂度O(nlgn),还能为霍夫曼树的优化作铺垫 //堆排序 #include<iostream> using namespace std; int arr[10001],n; inline int left(int i)//返回左儿子的数组下标,要用内联或宏定义写 { return 2*i; } inline int right(int i)//返回右儿子下标 { return 2*i+1; } void max_heapify(int arr[],int i)//维护最大堆的性质,即父亲数据必定大于儿子 { int l = left(i); int r = right(i); int largest;//最大数字的下标编号 //找出以i为父亲的三个结点中的最大值,记录最大值的下标编号 if(l <= n && arr[l] > arr[i]) largest = l; else largest = i; if(r <= n && arr[r] > arr[largest]) largest = r; if(largest != i)//如果最大值不是根结点 { swap(arr[i],arr[largest]);//交换这两个值 max_heapify(arr,largest);//递归维护,从被交换过的那个位置开始递归,因为从这个结点向下的树可能不满足堆性质 } } void build_max_heap(int arr[])//建堆 { for(int i = n/2;i >= 1;--i)//从数组的中点开始即可,对于完全二叉树而言,中间编号必为最后维护的非叶子结点 { max_heapify(arr,i); }//循环之后,整个数组满足堆性质 } void heap_sort(int arr[])//堆排序 { build_max_heap(arr);//先让数组具有堆性质,即构成最大堆 int len = n; for(int i = n;i >= 2;--i) { swap(arr[i],arr[1]);//arr[1]总是数组的最大数字,不断将其与数组最后一位交换,让最大的数放在数组最后面 n = n-1;//数组的最后一位无需再考虑 max_heapify(arr,1);//因为上一步骤的交换可能影响的最大堆的性质,从第一位开始维护它,让首位数字从上滚到下面属于它的位置 }//n-1次循环后(滚到最后最上面的数字必定最小)堆排序完成 } int main() { //freopen("in.txt","r",stdin); scanf("%d",&n); int len = n; for(int i = 1;i <= n;++i) { scanf("%d",&arr[i]); } heap_sort(arr); printf("%d/n",arr[(len+1)/2]); return 0; }