分治与递归——快速排序

       快速排序的基本思想可以这样来理解:对一组待排序元素,选定其中一个元素x为基准,将小于x的元素移动到其左边,将大于x的元素移动到其右边,然后对于x左边与右边的序列进行上述的操作直至排序完成。

       该算法时间复杂度最坏的情况出现在待排序列为正序或者逆序时。此时的时间复杂度为O(n2)

       平均时间复杂度为O(nlogn)

       源代码如下:

      

#include<iostream>




using namespace std;





void Swap(int &a, int &b) 
{
 int t = a;
 a = b;
 b = t;
}




/*划分函数*/
int Partition(int *array, int l, int r)
{
 int i = l, j = r + 1;
 int x = array[l];
 //比x小的元素交换到左边区域
 //比x大的元素交换到右边区域
 while (true)
 {
  while (array[++i] < x);
  while (array[--j] > x);
  if (i >= j)break;
  Swap(array[i], array[j]);
 }
 array[l] = array[j];
 array[j] = x;
 return j;
}
/*快速排序函数*/
void QuickSort(int *array,int l,int r)
{
 if (l < r) 
 {
  int t = Partition(array,l, r);
  QuickSort(array, l, t);
  QuickSort(array, t + 1, r);
 }
}




void main() 
{
 int temp[] = { 10,45,3,2,1,6,7,9,24,6 };
 cout << "排序前:" << endl;
 for(int i=0;i<10;i++)
 {
  cout << temp[i] << "\t";
 }
 cout << endl;
 QuickSort(temp, 0, 9);




 cout << "排序后:" << endl;
 for (int i = 0; i<10; i++)
 {
  cout << temp[i] << "\t";
 }
 cout << endl;
 system("pause");
}


         改进:如果每一次划分都产生一边是n-1个元素一边是1个元素的情况那么时间复杂度将变为O(n2),这显然不是我们所期望的,如果每次划分的两个区域大小为n/2那么时间复杂度将变为O(nlogn)。所以,快速排序算法的性能取决于划分的对称性。上述的代码中始终是以待排序列的第一个元素作为划分基准进行划分的,通过修改划分函数,可以设计出采用随机选择策略的快速排序算法,即在快速排序算法的每一步中当数组还没划分时,在待排序列随机选出一个划分基准,这样可以使划分基准是随机的,从而可以期望划分是较对称的

利用了随机划分的快速排序算法(10万个随机数)

#include<iostream>
#include<fstream>
#include<time.h>

using namespace std;

/*功能:生成随机数并存入文件
 *这里只是想试试这个方法
 *可以替换成别的产生随机数的方法
 */
void Randmoize()							
{
	int m = 1000000;
	int c = 101;
	int b = 91;
	int n = 0;
	fstream fout;
	fout.open("RandomFile.txt", ios::out);
	for (int i = 0; i < 100000; i++)
	{
		n = (n * c + b) % m;				//线性同余方程
		fout << n << "\n";
	};
	fout.close();
}

int temp[100000];										//存放待排序随机数的数组

/*读取文件中的随机数并存入数组*/
void ReadFile()											
{
	fstream fin;
	fin.open("RandomFile.txt", ios::in);
	for (int i = 0; i < 100000; i++)
	{
		fin >> temp[i];
	}
	fin.close();
}

void Swap(int &a,int &b)			
{
	int temp;
	temp = a;
	a = b;
	b = temp;
}

/*划分函数*/
int Partition(int *Array, int l, int r)		
{
	int i = l;
	int j = r + 1;
	int x = Array[l];
	while(true)								//将小于x的数放在其左边,大于x的数放在右边。
	{
		while (Array[++i] < x);
		while (Array[--j] > x);
		if (i >= j)break;
		Swap(Array[i], Array[j]);
	}
	Array[l] = Array[j];
	Array[j] = x;
	return j;
}

/*随机分组*/
int RandomizedPartition(int Array[], int l, int r)			//随机分组
{
	srand(time(NULL));
	int i = l + rand() % (r - l + 1);							//生成l~r之间的随机数
	Swap(Array[i], Array[l]);									//将随机得到的位置的值作为分组基准
	return Partition(Array, l, r);
}

/*快速排序函数*/
void QuickSort(int *Array, int l, int r)					
{
	if (l < r)
	{
		int q = RandomizedPartition(Array, l, r);
		QuickSort(Array, l, q - 1);
		QuickSort(Array, q + 1, r);
	}
}

void main()
{
	Randmoize();
	ReadFile();
	int l = 0, r = 99999;
	QuickSort(temp, l, r);

	fstream f;									//将排序好的序列保存至另一个文件
	f.open("SortedFile.txt", ios::out);
	for (int i = 0; i < 100000; i++)
	{
		f << temp[i] << "\n";
	}
	f.close();
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值