归并排序、堆排序与快速排序分析(2)

上一篇分析了归并排序过程,本篇将堆排序完结,同时分析快速排序过程。

通过build_max_heap,对给定的数据,建立一个最大堆结构,此时,堆排序任务已经完成了80%,建立好的最大堆,堆顶为最大元素,

输出堆顶,然后将最后叶子切换到堆顶,重新建立最大堆,再次输出堆顶,依次重复建立最大堆过程,直至输出输出所有元素,最后形成的序列即为

有序序列,降序序列。

程序里紧紧对过程模拟,输出堆顶后,赋值为-1,而不删除元素,模拟最终的输出:

    int i = 0;
    stringstream iss;
    for (; i < _arr_len; i++) {
        build_max_heap();

        //cout << _heap_arr[0] << " ";
        iss << _heap_arr[0] << " ";


        // swap 0 and last element
        _heap_arr[0] = -1;
       
    }

    cout << "final sequence is:";
    cout << iss.str() << endl;
    return 0;

3、快速排序

快排是目前所有排序算法中使用较多的排序,其基本的原理是:每次迭代都确定一个元素的最终位置,那么此时元素的左右区间,可以递归掉调用来确定每个区间的元素的最终位置,可见,每个区间内的调整都不需要进行

核心逻辑是,给定区间[p, r]如何确定其中一个元素的最终位置,算法导论中以a[r]为参考元素,确定其最终的位置,实现代码为

int QuickSort::get_arr_pivot(int p, int r)
{
    int key = _arr[r];

    // i 指向开始遍历前一个。
    int i = p - 1;

    for (;p < r; p++) {
        if (_arr[p] >= key) {
            continue;
            
            //如果当前元素比参考值要小,那么i自增,将i当前元素与p指向的值交换
            //这样i此时指向小于参考值元素
        } else if (_arr[p] < key) {
            i++;
            arr_swap(i, p);
        }
    }

    //遍历结束,i指向比key小的值,i+1是第一个大于key的元素
    //交换i+1与key
    //那么此时key的最终位置固定下来了,左右边为小于、大于它的区间
    //对子区间递归排序即可
    arr_swap(i + 1, r);

    return i + 1;
}

最终排序递归调用即可:

int QuickSort::quick_sort(int p, int r) 
{
    if (p < r) {
        int q = get_arr_pivot(p, r);
        
        print_arr();
        quick_sort(p, q-1);

        quick_sort(q+1, r);
    }

    return 0;
}

 

可以发现,快排是就地排序,而归并排序则是针对有序数据进行merge,需要借助额外空间。而快排则是就地排序,不用额外空间,每次递归就确定一个元素的最终位置,因此最终不用merge操作。

 

 

posted @ 2013-05-30 23:20  Crafet.36.77  阅读(208)  评论(0)    收藏  举报