快速排序--选取A[0]做主元,随机选取做主元,三点中值做主元

代码实现以及现象分析

//北航机试2020/3/28

/*
头中尾三位取中
针对不同的数据量
*/

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<algorithm>

using namespace std;

#define MAXN  10000000

int Cutoff = 50;

void Insertion_Sort(int A[],int N)
{
    int p,i;
    int temp;
    for(p = 1;p<N;p++)
    {
        temp = A[p];
        for(i = p;i>=1&&temp<A[i-1];i--)
        {
            A[i] = A[i-1];
        }
        A[i] = temp;
    }
}

int get_pivot(int A[],int Left,int Right,int op)
{
    int pivot;
    switch(op){
    case 1:
        {
            /*选取最左边的主元*/
            pivot = A[Left];
            break;
        }
    case 2:
        {
            /*随机选取主元*/
            int rand_index = rand()%(Right-Left+1) + Left;
            swap(A[Left],A[rand_index]);
            pivot = A[Left];
            break;
        }
    case 3:
        {
            /*三点选中值*/
            int center = (Left + Right)/2;
            if(A[Left]>A[center])
                swap(A[Left],A[center]);
            if(A[Left]>A[Right])
                swap(A[Left],A[Right]);
            if(A[center]>A[Right])
                swap(A[center],A[Right]);

            swap(A[center],A[Left]);
            pivot = A[Left];
            break;
        }
    default:
        {
            break;
        }
    }
    return pivot;
}

int Partition(int A[],int Left,int Right)
{


    /*
    int rand_index = rand()%(Right-Left+1) + Left;
    swap(A[Left],A[rand_index]);
    int pivot = A[Left];
    */
    int pivot = get_pivot(A,Left,Right,3);
    while(Left < Right)
    {


        //使用的是元素相等的时候继续移动指针
        while(Left < Right && A[Right] >= pivot) --Right;
        A[Left] = A[Right];
        while(Left < Right && A[Left] <=  pivot) ++Left;
        A[Right] = A[Left];
    }
    A[Left] = pivot;
    return Left;
}


void Qsort(int A[],int Left,int Right)
{
    //if(Left<Right)
    if(Cutoff<=Right-Left)//使用Cutoff阈值
    {
        int pivot_pos = Partition(A,Left,Right);
        Qsort(A,Left,pivot_pos-1);
        Qsort(A,pivot_pos+1,Right);
    }
    //
    else
    {
        Insertion_Sort(A+Left,Right-Left+1);
    }
}

void Quick_Sort(int A[],int N)
{
    Qsort(A,0,N-1);
}


void print(int A[],int N)
{
    int i;
    for(i = 0;i<N;i++)
    {
        if(i == N-1)
            printf("%d\n",A[i]);
        else
            printf("%d ",A[i]);
    }
}


void test(int A[],int arg_Cutoff)
{
    Cutoff = arg_Cutoff;
    clock_t start,end;
    start = clock();
	Quick_Sort(A,MAXN);
	end = clock();
	printf("执行时间Cutoff=%d %f s\n",Cutoff,(double)(end-start)/CLOCKS_PER_SEC);
}


int A1[MAXN],A2[MAXN],A3[MAXN],A4[MAXN],A5[MAXN],A6[MAXN];

int main()
{


    int i;

    srand((unsigned)time(NULL));

	for(i = 0;i<MAXN;i++)
	{
		 A6[i] = A5[i]=A4[i] = A3[i]=A2[i] = A1[i] = rand();
	}

	test(A1,50);
	test(A2,100);
	test(A3,200);
	test(A4,300);
	test(A5,400);
	test(A6,1);
    return 0;
}
/*
MAXN 1000000
不同的实现方法
1.选用A[0]做主元
执行时间Cutoff=50  0.138000 s
执行时间Cutoff=100 0.224000 s
执行时间Cutoff=200 0.210000 s
执行时间Cutoff=300 0.228000 s
执行时间Cutoff=400 0.271000 s
执行时间Cutoff=1   0.172000 s
2.选用随机主元
执行时间Cutoff=50  0.149000 s
执行时间Cutoff=100 0.188000 s
执行时间Cutoff=200 0.192000 s
执行时间Cutoff=300 0.226000 s
执行时间Cutoff=400 0.272000 s
执行时间Cutoff=1   0.198000 s
3.使用三点取中值
执行时间Cutoff=50  0.139000 s
执行时间Cutoff=100 0.161000 s
执行时间Cutoff=200 0.187000 s
执行时间Cutoff=300 0.229000 s
执行时间Cutoff=400 0.274000 s
执行时间Cutoff=1   0.171000 s

MAX = 10000000(千万级)
1.选用A[0]做主元
执行时间Cutoff=50  4.392000 s
执行时间Cutoff=100 4.241000 s
执行时间Cutoff=200 3.679000 s
执行时间Cutoff=300 3.048000 s
执行时间Cutoff=400 2.603000 s
执行时间Cutoff=1   4.477000 s
2.选用随机主元*********************
执行时间Cutoff=50  4.754000 s
执行时间Cutoff=100 4.417000 s
执行时间Cutoff=200 3.688000 s
执行时间Cutoff=300 3.020000 s
执行时间Cutoff=400 2.649000 s
执行时间Cutoff=1   4.752000 s
3.使用三点取中值******************
执行时间Cutoff=50  3.838000 s
执行时间Cutoff=100 3.730000 s
执行时间Cutoff=200 3.270000 s
执行时间Cutoff=300 2.814000 s
执行时间Cutoff=400 2.479000 s
执行时间Cutoff=1   3.966000 s

千万级别现象的解释:
你会发现如果序列不是有序或者逆序的话,选用A[0]做主元,的效果还行,比随机函数要好
会发现选用A[0]做主元会比选用随机算法的运行时间节省
使用三点取中值会发现效果比较好,主要使得子集的划分均匀

个人觉着选取主元只是尽量避免最坏情况的产生,以及趋向于最好情况。
*/


发布了71 篇原创文章 · 获赞 36 · 访问量 9433

猜你喜欢

转载自blog.csdn.net/qq_34686440/article/details/105172452