• C++编程练习(16)----“排序算法 之 快速排序“


    快速排序

    基本思想:

    通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的。

    算法介绍:

    设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
    一趟快速排序的算法是:
    1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
    2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
    3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]赋给A[i];
    4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]赋给A[j];
    5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[j]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。

    下图动态展示了快速排序的一个过程,该图片是维基共享资源特色图片(Featured pictures),并被视为最好的图像之一。


    具体代码如下:

    1、排序前的一些准备工作,建立合适的排序需要的结构。

    /********* 排序用到的结构  头文件sort_struct.h ************/
    #include <ctime>
    #include <cstdlib>
    #include <iostream>
    #define MAXSIZE 100000000 //要排序数组个数最大值
    
    
    class SqList{
    public:
    	int r[MAXSIZE+1];
    	int length;
    };
    
    /* 交换L中数组r下标为i和j的值 */
    void swap(SqList *L, int i, int j)
    {
    	int temp = L->r[i];
    	L->r[i] = L->r[j];
    	L->r[j] = temp;
    }
    
    /* 显示数组内容 */
    void showSqList(SqList *L)
    {
    	for(int i=1;i<=L->length;i++)
    		std::cout<<L->r[i]<<"  ";
    	std::cout<<std::endl;
    }
    
    /* 为数组随机产生一串数字 */
    double random(double start, double end)
    {
        return start+(end-start)*rand()/(RAND_MAX + 1.0);
    }
    void RandomCreat(SqList *L,int len)
    {	
    	double random(double,double);
        srand(unsigned(time(0)));
    	for(int i=1;i<=len;i++)
    	{
    		L->r[i] = int(random(0,10000));
    	}
    }

    2、编写主文件,实现排序与测试。

    #include"sort_struct.h"
    using namespace std;
    
    void QSort(SqList *L,int low,int high);
    int Partition(SqList *L,int low,int high);
    
    /* 对顺序表L作快速排序 */
    void QuickSort(SqList *L)
    {
    	QSort(L,1,L->length);
    }
    
    /* 对顺序表L中的子序列L->r[low...high]作快速排序 */
    void QSort(SqList *L,int low,int high)
    {
    	int pivot;
    	if(low < high)
    	{
    		pivot = Partition(L,low,high);	//将L->r[low...high]一分为二,算出枢轴值pivot
    		QSort(L,low,pivot-1);	//对低子表递归排序
    		QSort(L,pivot+1,high);	//对高子表递归排序
    	}
    }
    
    /* 交换顺序表L中子表的记录,使枢轴记录到位,并返回其所在位置 */
    /* 此时在它之前(后)的记录均不大(小)于它。 */
    int Partition(SqList *L,int low,int high)
    {
    	int pivotkey;
    	pivotkey = L->r[low];	//用子表的第一个记录作枢轴记录
    	while(low<high)	//从表的两端交替向中间扫描
    	{
    		while(low<high && L->r[high]>=pivotkey)
    			high--;
    		swap(L,low,high);	//将比枢轴记录小的记录交换到低端
    		while(low<high && L->r[low]<=pivotkey)
    			low++;
    		swap(L,low,high);	//将比枢轴记录大的记录交换到高端
    	}
    	return low;		//返回枢轴所在位置
    }
    
    int main()
    {
    	SqList *L = new SqList;
    	L->length = 10;
    	RandomCreat(L,L->length);
    	cout<<"快速排序前:";
    	showSqList(L);
    	cout<<"快速排序后:";
    	QuickSort(L);
    	showSqList(L);
    	return 0;
    }

    Partition 函数要做的,就是先选取当中的一个关键字,比如选择第一个关键字50,然后想尽办法将它放到一个位置,使得它左边的值都比它小,右边的值都比它大,这样的关键字称为枢轴(pivot)。

    运行结果如下:



  • 相关阅读:
    1046 Shortest Distance (20 分)(模拟)
    1004. Counting Leaves (30)PAT甲级真题(bfs,dfs,树的遍历,层序遍历)
    1041 Be Unique (20 分)(hash散列)
    1036 Boys vs Girls (25 分)(查找元素)
    1035 Password (20 分)(字符串处理)
    1044 Shopping in Mars (25 分)(二分查找)
    onenote使用小Tip总结^_^(不断更新中...)
    1048 Find Coins (25 分)(hash)
    三个故事
    领导者的举止
  • 原文地址:https://www.cnblogs.com/fengty90/p/3768832.html
Copyright © 2020-2023  润新知