快速排序的应用

1、把序列中的正负数分开

举例:

序列:0,2,-1,4,-2,-3,6,7,-9,10

处理好的序列:-9 -3 -1 -2 4 2 6 7 0 10

注意:

仅仅把正负数分开就好,正数和负数里面不要求次序

不要求排序,这里遍历一遍序列就可以了,时间复杂度为O(n)

//应用一:把序列中的正负数分开算法
#include <iostream>
using namespace std;
const int len = 10;
void Divide(int arr[],int n);
int main()
{
	int arr[len]={0,2,-1,4,-2,-3,6,7,-9,10};
	//int arr[len]={1,2,1,4,2,3,6,7,9,10};
	Divide(arr,len);
	for (int i=0;i<len;i++)
	{
		cout<<arr[i]<<" ";
	}
	system("pause");
}

/*进行一次快速排序即可*/

void Divide(int arr[],int n)
{
	int temp;
	int low=0;
	int high = n-1;
	while (low<high)
	{
		while (low<high && arr[low]<0)
		{
			low++;
		}
		while (low < high && arr[high]>=0)
		{
			high--;
		}
		if (low < high)//满足此式时,表示遇到了arr[low]指向正数,但是arr[high]指向负数的情况,这时需要互换元素
		{
			temp = arr[low];
			arr[low]=arr[high];
			arr[high]=temp;
			//互换后,low和high位置已经处理完毕,这时下标要往前移动一位---不要忘了啊
			low++;
			high--;
		}
	}
}

2、查找第j小的元素

//应用二:查找第j小的元素
#include <iostream>
using namespace std;

const int len =10000;
template<class T>
T QSort(T arr[],int n,int j);
template<class T>
int Partition(T arr[],int low,int high);

int main()
{
	int arr[len];
	for (int i=0;i<len;i++)
	{
		arr[i]=rand()%100;
	}
	
	cout<<"第"<<7<<"个数为:"<<QSort(arr,len,6)<<endl;

	system("pause");
	return 0;
}

template<class T>
T QSort(T arr[],int n,int j)
{
	int low = 0;
	int high = n-1;
	int keyLoc = Partition(arr,low,high);
	while (keyLoc != j)
	{
		if (keyLoc > j)
		{
			keyLoc = Partition(arr,low,keyLoc-1);
		}
		else
		{
			keyLoc = Partition(arr,keyLoc+1,high);
		}
	}
	return arr[j];
}

template<class T>
int Partition(T arr[],int low,int high)
{
	T key = arr[low];
	while (low < high)
	{
		while (low < high && arr[high] >= key)
		{
			high--;
		}
		arr[low] = arr[high];
		while (low<high && key >= arr[low])
		{
			low++;
		}
		arr[high] = arr[low];
	}
	arr[low] = key;
	return low;
}

3、荷兰国旗

//应用三:荷兰国旗
//思想:可以视为数组的排序问题,这个数组可以分为 前部 中部和后部,当前边和后面拍好后,数组自动排好了
//具体思路:
//前提:使用j进行对数组进行遍历,i指向红色区,k指向蓝色区--(j左边和k右边的元素全被处理过)
//效果:0 - i-1:红色  i - k-1:白色  k - n-1:蓝色
//1、j遍历到的位置为1(红)时,说明它一定在前部,
//	则直接和i进行交换即可,这里i始终指向以确定白色位置的下一位,并且i和j均想前走一步(++)
//2、j遍历到的位置为2(白)时,说明它一定在中部,
//	则该元素不动,j向先走一步,处理下一个位置
//3、j遍历到的位置为3(蓝)时,说明它一定在后部,
//	则直接和k进行交换,这里k始终指向确定是蓝色位置的前一位(倒着走的),这时k应--,但是此时j不能向前走,
//	刚换过来的元素是还没处理过的,这时j往前走,就会把该元素忽略(j左边和k右边的元素全被处理过)
//这里一直担心的问题是,出现“22211”时怎么处理:见2时往前走,见到第一个1时,应该和第一个2交换,这时1就和2换位置了,刚刚可以满足题意


#include <iostream>
using namespace  std;
const int len = 10;
void FlagAdjust(int arr[],int n);
void Show(int arr[],int n);
int main()
{
	int arr[len];
	for (int i=0;i<len;i++)
	{
		arr[i]=rand()%3 + 1;
	}
	Show(arr,len);
	FlagAdjust(arr,len);
	Show(arr,len);
	system("pause");
	return 1;
}

void FlagAdjust(int arr[],int n)
{
	int i=0;
	int j=0;
	int k=n-1;
	int temp;
	while (j<k)
	{
		if (arr[j]==1)//红色
		{
			temp =arr[i];
			arr[i]=arr[j];
			arr[j]=temp;
			i++;
			j++;
		}
		else if (arr[j]==2)//2代表白色
		{
			j++;
		}
		else//3代表蓝色
		{
			temp=arr[j];
			arr[j]=arr[k];
			arr[k]=temp;
			k--;
		}
	}
}

void Show(int arr[],int n)
{
	for (int i=0;i<len;i++)
	{
		switch (arr[i])
		{
		case 1:
			cout<<"红";
			break;
		case 2:
			cout<<"白";
			break;
		case 3:
			cout<<"蓝";
			break;
		}
	}
	cout<<endl;
}

4、快排的非递归程序,这里是固定选择枢轴的版本

/*快排的非递归代码*/
#include <iostream>
using namespace std;
const int len = 10;
struct node
{
	int low;
	int high;
};
void QSort(int arr[],int n);
int main()
{
	int arr[len];
	for (int i=0;i<len;i++)
	{
		arr[i]=rand()%100;
	}
	//排序前结果
	for (int i=0;i<len;i++)
	{
		cout<<arr[i]<<" ";
	}
	cout<<endl;
	//快速排序
	QSort(arr,len);
	//排序后结果
	for (int i=0;i<len;i++)
	{
		cout<<arr[i]<<" ";
	}
	cout<<endl;
	system("pause");
	return 1;
}
void QSort(int arr[],int n)
{
	int top=-1;
	struct node stack[len];
	int low =0;
	int high=0;
	top++;
	stack[top].low = 0;
	stack[top].high = n-1;
	while (top>-1)
	{
		//出栈
		low = stack[top].low;
		high = stack[top].high;
		top--;
		while (low < high)
		{
			//这里引入first和low的原因:low和high在下面的一次快排中会发生变化,
			//而根据最终枢轴位置还要把原数据分成两段,这时需要记录本次待排序数据长度的首尾下标
			int first = low;
			int last = high;
			//一次快排
			int key = arr[low];
			while (low<high)
			{
				while (high > low && arr[high] > key)
				{
					high--;
				}
				arr[low]=arr[high];
				while (high > low && arr[low] < key)
				{
					low++;
				}
				arr[high] = arr[low];
			}
			arr[low]=key;
			//枢轴把数据分成两段,这时需要把这两段待排序的两下标都放入栈中,之后进行依次出栈进行排序
			//枢轴左半段入栈
			top++;
			stack[top].low = first;
			stack[top].high = low -1;
			//枢轴右半段入栈
			top++;
			stack[top].low = low+1;
			stack[top].high = last;
		}
	}
}



 


 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值