数据结构知识整理 - 快速排序

版权声明: https://blog.csdn.net/Ha1f_Awake/article/details/85483643

快速排序(Quick Sort)

(可先回顾“排序算法”)

交换排序的基本思想两两比较待排序记录的关键字,一旦发现两个记录不满足次序要求时则进行交换,直到整个序列全部满足要求为止。

冒泡排序(Bubble Sort)是一种最简单的交换排序方法,它通过两两比较相邻记录的关键字,逆序则交换,从而使关键字较小的记录如气泡一般逐渐往上“漂浮”(左移),或者使关键字较大的记录如石块一般“沉落”(右移)。从右往左进行交换更接近“冒泡”的含义,而从左往右交换更像是“沉石”的过程。(可回顾“这里”)

在冒泡排序中,需要安排一个变量flag表示排序循环结束的标志。flag = 0表示在本趟排序中没有发生“交换”,即排序已经完成;反之,若flag = 1,继续进行排序。

快速排序由冒泡排序改进得到。冒泡排序中只能比较相邻的记录,所以每次“交换”只能消除一个逆序。而快速排序能够比较两个不相邻的记录,通过一次“交换”消除多个逆序,从而大大加快排序的速度。

<逻辑思路>

1)在待排序的n个记录中选择任意一个记录(通常选择第一个记录)作为枢轴(支点),设其关键字为pivotkey。经过一趟排序后,所有关键字小于pivotkey的记录“交换”到序列前面,所有关键字大于pivotkey的记录交换到序列后面,最后将枢轴记录插在中间;

2)不断重复上述过程,直至每一部分只包含一个记录。

<实现思路>

1)在待排序序列首尾设置指针low、high。初始化时,指针low指向rcds[1],指针high指向rcds[L.length];

2)将rcds[1]的信息暂存在rcds[0],此时rcds[1]包含的记录作为枢轴,rcds[1]的位置作为空位

3)指针low从左往右查找关键字大于pivotkey的记录,指针high从右往左查找关键字小于pivotkey的记录;

4)因为空位在前半部分,所以指针high首先开始查找关键字小于pivotkey的记录。假设找到的是rcds[n]上的记录,找到后将其记录存放在空位,存储后空位便由rcds[1]改为rcds[n],即空位出现在后半部分;

5)指针low开始查找关键字大于pivotkey的记录,并将记录存放在后半部分的空位,同时“生成”新的空位;

6)不断重复(4)(5)的过程,直至low == high,而且此时rcds[low](或rcds[high])正是枢轴记录的存放位置。

7)对前后部分分别重复上述操作,直至所有部分都只包含一个记录(递归)。

/*--------在一趟排序中切分前后部分,并返回枢轴位置--------*/

int Slice_n_Pivot(SqList &L, int low, int high)
{
    L.rcds[0] = L.rcds[1];            /*暂存枢轴记录*/
    int pivotkey = L.rcds[1].key;     /*初始化pivotkey*/

    while(low < high)                 /*当low未与high重合时*/
    {
        /*指针high从右往左移动,找到(第一个)关键字小于pivotkey的记录*/
        while((low < high) && (L.rcds[high].key >= pivotkey)) high--;    
        
        L.rcds[low] = L.rcds[high];   /*将找到的记录存放在前半部分的空位,同时得到新的空位*/

        /*指针low从右往左移动,找到(第一个)关键字大于pivotkey的记录*/
        while((low < high) && (L.rcds[low].key <= pivotkey)) low++;

        L.rcds[high] = L.rcds[low];
    }

    L.rcds[low] = L.rcds[0];          /*或L.rcds[high] = L.rcds[0];*/

    return low;               /*返回枢轴的位置,作为前半部分指针high和后半部分指针low的依据*/
}

       
/*----------在前后部分中递归-----------*/

void Recursive(SqList &L, int low, int high)
{
    if(low < high)
    {
        pivot = Slice_n_Pivot(L, low, high);

        /*因为在每次递归中low与high的值都会发生相应的变化,所以不需要再初始化实参*/       
        Recursive(L, low, pivot-1);    /*在前半部分递归排序*/

        Recursive(L, pivot+1, high);   /*在后半部分递归排序*/
    }
}

/*-----------总结快速排序------------*/

void Quick_Sort(SqList &L)
{
    Recursive(L, 1, L.length);
}

猜你喜欢

转载自blog.csdn.net/Ha1f_Awake/article/details/85483643