【Algorithm】堆排,C++实现

对一个数组中的元素按照顺序构建二叉树,就形成了一个(二叉)堆。(二叉树是虚拟的,并不是真的建立二叉树)

表示堆的数组A有两个重要属性:A.heapSize,表示堆里面有多少元素,数组里有多少元素在堆里

           A.length,表示数组长度      

例如数组A= {1,2,3,4,5,6,7,8,9,10},此时A.heapSize = A.length。除了最后一层之外,这个二叉树是完满的

最大堆:父节点的值总是不小于子节点的值,反应在数组中就是A[i]>=A[2i+1] && A[i]>=A[2i+2],如果2i+2<A.size的话

最小堆:父节点的值总是不大于子节点的值,反应在数组中就是A[i]<=A[2i+1] && A[i]<=A[2i+2],如果2i+2<A.size的话,上图就是一个最小堆

 

堆排一般用最大堆,输出升序数组,最小堆用于优先队列。

堆排的时间复杂度是O(nlgn)

我写的是最小堆排序,输出降序数组

 

//=================== 最小堆维护 ==================
// 调整根节点为arr[i]的子树顺序,将最小的节点放到根节点位置
// 递归调整被置换的子节点
void minHeapfy(vector<int> &arr, int i, int heapSize){
    int left = 2 * i + 1;  //对于arr[i],它的左孩子是arr[2i+1]右孩子是arr[2i+2]
    int right = 2 * i + 2;
    int least = i;
    
    if (left < heapSize && arr[left] < arr[least])
        least = left;

    if (right < heapSize && arr[right] < arr[least]){
        least = right;
    }

    if (least != i){
        int temp = arr[i];
        arr[i] = arr[least];
        arr[least] = temp;
        minHeapfy(arr, least, heapSize);  //如果子树发生变动,递归调整有变动的子节点
    }
}

//=============== 建立最小堆 ================
// 利用minHeapfy调整每一棵子树,arr中arr[arrSize/2:]的元素都是叶子节点
void buildMinHeap(vector<int> &arr){
    int heapSize = arr.size();
    for (int i = heapSize/2-1; i >= 0; i--){
        minHeapfy(arr, i, heapSize);    
    }
}

// ================ 输出堆排结果 ====================
//由于根节点总是全堆最小的,每次置换根节点与最后一个节点
//对被置换之前的数组进行最小堆建立
void heapSort(vector<int> &arr){
    int heapSize = arr.size();
    buildMinHeap(arr);
    for (int i = heapSize - 1; i >= 0; i--){
        int temp = arr[0]; //置换根节点元素和当前数组最后一个元素
        arr[0] = arr[i];
        arr[i] = temp;

        heapSize -= 1;
        minHeapfy(arr, 0, heapSize); //对有序元素之前的节点建立最小堆
    }
}


int _tmain(int argc, _TCHAR* argv[])
{
    vector<int> primes = { 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 };

    heapSort(primes);
    for (int i = 0; i < primes.size(); i++){
        cout << primes[i] << endl;
    }

    system("pause");
    return 0;
}

 

posted @ 2016-04-27 11:17  料峭  Views(409)  Comments(0Edit  收藏  举报