快速排序的优化与非递归

#define _CRT_SECURE_NO_WARNINGS 1
#include "SwapSort.h"
#include "Stack.c"


int GetMidIndex(int* a,int begin,int end)
{
	int mid = (begin+end) / 2;
	if (a[begin]<a[mid])
	{
		if (a[mid]<a[end]) // a[begin]
		{
			return mid;
		}
		else if (a[begin] > a[mid]) //a[begin]a[end]; a[begin]>a[end]
		{
			return begin;
		}
		else // a[begin]a[end]; a[end]>a[begin]
		{
			return end;
		}
	}
	else // a[begin]>a[mid]
	{
		if (a[mid]>a[end])
		{
			return mid;
		}
		else if (a[begin]>a[end]) // a[begin]a[end]
		{
			return begin;
		}
		else
		{
			return end;
		}
	}
}


int PartSort(int* a, int begin, int end)
{
	int prev = begin;
	int cur = begin + 1;
	int keyi = begin;

	//加入“三数取中”的优化
	int midi = GetMidIndex(a, begin, end);
	Swap(&a[keyi], &a[midi]);

	while (cur<=end)
	{
      //cur位置的值小于keyi位置的值
	  /*if (a[cur]

		if (a[cur]<a[keyi])
		{
			prev++;
			Swap(&a[prev], &a[cur]);
		}
		cur++;
	}
	Swap(&a[prev],&a[keyi]);
	keyi = prev;

	return keyi;
}


static void InsertSort(int* a, int n)
{
	//整体排序
	for (int i = 0; i < n - 1; i++)
	{
		//单趟排序
		// [0,end]有序,把end+1位置的值插入,保持有序
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (tmp < a[end])
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;
			}
		}
		a[end + 1] = tmp;
	}
}

//快排的时间复杂度:
//当每次选择的key为中间大小时,效率最高;时间复杂度为:O(N*logN)
//当每次选择的key为最大值或最小值时,效率最低;时间复杂度为:O(N^2)。【此外,数据量稍大一些,会出现栈溢出】

//一、优化
//优化1:三数取中;第一个 中间 最后一个,选三个中既不是最大,也不是最小的值。
void QuickSort(int* a, int begin,int end)
{
	//区间不存在,或者只有一个值则不需要再处理
	if (begin>=end)
	{
		return;
	}

	if (end-begin>10)
	{
		int keyi = PartSort(a, begin, end);

		// [begin,keyi-1] keyi [keyi+1,end]
		QuickSort(a, begin, keyi - 1);
		QuickSort(a, keyi + 1, end);
	}
	//优化2;小区间排序:当递归划分小区间,区间比较小的时候,就不再递归划分去排序这个小区间。可以考虑直接用其它排序
    //对小区间进行处理(常用的是:直接插入排序)
	//当区间小于10时,就进行直接插入排序
	else  
	{
		InsertSort(a+begin,end-begin+1);
	}
}

//二、将递归改为非递归
//要求掌握,递归改成非递归
//递归大问题,极端场景下,如果深度太深,会出现栈溢出
//1、直接改循环【比如斐波那契数、归并排序】
//2、用数据结构栈模拟实现递归过程【数据结构栈开辟的空间均在堆区,无内存压力】

void QuickSortNonR(int* a,int begin,int end)
{
	ST st;
	StackInit(&st);
	StackPush(&st,end);
	StackPush(&st,begin);

	while (!StackEmpty(&st))
	{
		int left = StackTop(&st);
		StackPop(&st);
		int right = StackTop(&st);
		StackPop(&st);

		int keyi = PartSort3(a,left,right);
		//[left,keyi-1] keyi [keyi+1,right]
		
		if (keyi+1<right)
		{
			StackPush(&st, right);
			StackPush(&st, keyi+1);
		}

		if (left < keyi - 1)
		{
			StackPush(&st, keyi - 1);
			StackPush(&st, left);
		}
	}

	StackDestroy(&st);
}




你可能感兴趣的:(数据结构,算法,排序算法)