【数据结构】快排专题

目录

快排递归:

版本1:左右指针

单趟:

完整代码: 

优化(三数取中): 

版本2:挖坑法

单趟:

完整代码: 

版本3:前后指针

快排非递归:


快排递归:

版本1:左右指针

单趟:

//单趟
int PartSort(int*a, int left, int right)
{
	/*int mid = GetMidIndex(a, left, right);
	swap(&a[left],&a[mid]);*/
	int key = left;
	while (left < right)
	{
		//左边做key,右边先走找小的
		while (left < right && a[right] >= a[key])
		{
			right--;
		}
		//左边再走,找大
		while (left < right && a[left] <= a[key])
		{
			left++;
		}
		//交换,把大的换到右边,小的换到左边
		swap(&a[left], &a[right]);
	}
	swap(&a[key],&a[right]);
	return right;
}

思考:单趟排完,如何让key左边区间有序,key右边区间有序

--------->类似递归

思路如图: 

完整代码: 

void swap(int* px, int* py)
{
	int tmp = *px;
	*px = *py;
	*py = tmp;
}

//单趟
int PartSort(int*a, int left, int right)
{
	int key = left;
	while (left < right)
	{
		//左边做key,右边先走找小的
		while (left < right && a[right] >= a[key])
		{
			right--;
		}
		//左边再走,找大
		while (left < right && a[left] <= a[key])
		{
			left++;
		}
		//交换,把大的换到右边,小的换到左边
		swap(&a[left], &a[right]);
	}
	swap(&a[key],&a[right]);
	return right;
}

void QuickSort(int* a, int left,int right)
{
	if (left < right)
	{
		int keyi = PartSort(a, left, right);
		//[left,keyi-1]  keyi  [keyi+1,right]
		PrintSort(a+left, right-left+1);
		QuickSort(a, left, keyi - 1);
		QuickSort(a, keyi + 1, right);
	}
}
void TestQuickSort()
{
	int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };//{ 5, 7, 4, 8, 6, 3, 9, 1, 2 };
	int n = sizeof(a) / sizeof(int);
	QuickSort(a, 0, n - 1);
	PrintSort(a,n);
}

思考:时间复杂度? 

思考:有无什么解决办法能让快排在有序的情况下时间复杂度不是O(N^2)

-------->是由于选key导致的  

 ​

优化(三数取中): 

通过三相取中,使得时间复杂度不会出现最坏的情况

三相取中使得有序的情况一直二分下去,例:1,2,3,4,5,6,7,8,9

//三数取中
int GetMidIndex(int*a, int left, int right)
{
	int mid = left + (right - left) / 2;
	if (a[left] < a[mid])
	{
		if (a[mid] < a[right])
		{
			return mid;
		}
		else if (a[left] > a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
	else
	{
		if (a[mid] > a[right])
		{
			return mid;
		}
		else if (a[left] < a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
}
void swap(int* px, int* py)
{
	int tmp = *px;
	*px = *py;
	*py = tmp;
}

//单趟
int PartSort(int*a, int left, int right)
{
	int mid = GetMidIndex(a, left, right);
	swap(&a[left],&a[mid]);
	int key = left;
	while (left < right)
	{
		//左边做key,右边先走找小的
		while (left < right && a[right] >= a[key])
		{
			right--;
		}
		//左边再走,找大
		while (left < right && a[left] <= a[key])
		{
			left++;
		}
		//交换,把大的换到右边,小的换到左边
		swap(&a[left], &a[right]);
	}
	swap(&a[key],&a[right]);
	return right;
}

void QuickSort(int* a, int left,int right)
{
	if (left < right)
	{
		int keyi = PartSort(a, left, right);
		//[left,keyi-1]  keyi  [keyi+1,right]
		PrintSort(a+left, right-left+1);
		QuickSort(a, left, keyi - 1);
		QuickSort(a, keyi + 1, right);
	}
}
void TestQuickSort()
{
	int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };//{ 5, 7, 4, 8, 6, 3, 9, 1, 2 };
	int n = sizeof(a) / sizeof(int);
	QuickSort(a, 0, n - 1);
	PrintSort(a,n);
}

版本2:挖坑法

单趟:

int PartSort2(int* a, int left, int right)
{
	int mid = GetMidIndex(a, left, right);
	swap(&a[left], &a[mid]);
	int key = a[left];
	int hole = left;
	while (left < right)
	{
		//右边去找小,填到左边的坑里面
		while (left < right && a[right] >= key)
		{
			right--;
		}

		//把右边找的小的,填到左边的坑,自己形成新的坑
		a[hole] = a[right];
		hole = right;

		//左边去找大,填到右边的坑里面
		while (left < right && a[left] <= key)
		{
			left++;
		}
		//把左边找的大的,填到右边的坑,自己形成新的坑
		a[hole] = a[left];
		hole = left;
	}
	a[hole] = key;
	return hole;
}

完整代码: 

//挖坑法
void swap(int* px, int* py)
{
	int tmp = *px;
	*px = *py;
	*py = tmp;
}
//三数取中
int GetMidIndex(int*a, int left, int right)
{
	int mid = left + (right - left) / 2;
	if (a[left] < a[mid])
	{
		if (a[mid] < a[right])
		{
			return mid;
		}
		else if (a[left] > a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
	else
	{
		if (a[mid] > a[right])
		{
			return mid;
		}
		else if (a[left] < a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
}
int PartSort2(int* a, int left, int right)
{
	int mid = GetMidIndex(a, left, right);
	swap(&a[left], &a[mid]);
	int key = a[left];
	int hole = left;
	while (left < right)
	{
		//右边去找小,填到左边的坑里面
		while (left < right && a[right] >= key)
		{
			right--;
		}

		//把右边找的小的,填到左边的坑,自己形成新的坑
		a[hole] = a[right];
		hole = right;

		//左边去找大,填到右边的坑里面
		while (left < right && a[left] <= key)
		{
			left++;
		}
		//把左边找的大的,填到右边的坑,自己形成新的坑
		a[hole] = a[left];
		hole = left;
	}
	a[hole] = key;
	return hole;
}
void QuickSort(int* a, int left, int right)
{
	if (left < right)
	{
		int keyi = PartSort2(a, left, right);
		//[left,keyi-1]  keyi  [keyi+1,right]
		//PrintSort(a + left, right - left + 1);
		QuickSort(a, left, keyi - 1);
		QuickSort(a, keyi + 1, right);
	}
}
PrintSort(int*a, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}
void TestQuickSort()
{
	int a[] = { 6, 1, 2, 7, 9, 3, 4, 5, 10, 8 };//{ 5, 7, 4, 8, 6, 3, 9, 1, 2 };
	int n = sizeof(a) / sizeof(int);
	//QuickSort(a, 0, n - 1);
	QuickSort(a, 0, n - 1);
	PrintSort(a, n);
}

版本3:前后指针

void swap(int*x,int*y)
{
	int tmp = *x;
	*x = *y;
	*y = tmp;
}
int PartSort3(int*a, int left, int right)
{
	int keyi = left;
	int prev = left;
	int cur = prev + 1;
	while (cur <= right)
	{
		if (a[cur] < a[keyi] && prev++ != cur)//当prev与cur不相等的时候交换,相等的话就没必要交换
			swap(&a[prev],&a[cur]);
			cur++;
		/*if (a[cur] < a[keyi])
		{
			prev++;
			if (a[prev] > a[keyi])
			{
				swap(&a[prev], &a[cur]);
				cur++;
			}
			else
			{
				cur++;
			}
		}
		else
		{
			cur++;
		}*/
	}
	swap(&a[prev],&a[keyi]);
	return prev;
}
PrintSort(int*a,int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ",a[i]);
	}
}
int main()
{
	int a[] = { 6, 1, 2, 7, 9, 3, 4, 5, 10, 8 };
	int n = sizeof(a) / sizeof(int);
	int left = 0;
	int right = n - 1;
	int ret = PartSort3(a,0,n-1);
	printf("%d\n",ret);
	PrintSort(a,n);
	return 0;
}

快排非递归:

void QuickSortNonR(int* a, int left, int right)
{
	ST st;
	StackInit(&st);
	StackPush(&st,right);
	StackPush(&st, left);
	while (!StackEmpty(&st))
	{
		int begin = StackTop(&st);
		StackPop(&st);

		int end = StackTop(&st);
		StackPop(&st);

		int keyi = PartSort3(a,begin,end);
		//[begin,keyi-1] keyi [keyi+1,end]
		if (keyi + 1 < end)
		{
			StackPush(&st, end);
			StackPush(&st, keyi+1);
		}
		if (keyi - 1 > begin)
		{
			StackPush(&st, keyi-1);
			StackPush(&st, begin);
		}
	}
	StackDestroy(&st);
}
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值