快速排序(qsort) 代码层分析

快速排序在我看来,他是一种排序思想:(以升序为例)
1.取预排序序列中的一个数作为划分值
2.从序列中找到两个数——在序列左侧的值大的数,序列右侧的值小的数(值的大小以划分数为标准)
3.交换位置
4然后再进一步对两边数作1、2、3操作,直至成为目标序列。这1、2、3、4步操作均可以不同的方式来写,来优化。

提一下:
sort在c++的<algorithm>头文件中,模板:sort(begin,end,compare); || sort(begin, end);
数组a,从0开始存,n个数
begin为数组预排序序列首地址可为a 或string类型的数组用 s.begin()  (咦,这也就是说可以选择部分位置的数来排类似sort(a+3, a+n),已验证)
end为数组预排序序列的尾地址(最后一个数的下一位)即a+n 或string类型的数组用 s.end()
compare为自定义比较函数,不写则默认为升序,否则需定义类似
 bool compare(int a, int b)//(int)类型根据序列类型来定
{
    return a > b;// > 号则为降序  < 为升序
}

网上还看到可以include<functional>,用里面的比较函数对象less<type>、greater<type>
升序:sort(begin,end,less<data-type>());
降序:sort(begin,end,greater<data-type>()).

参考链接:https://blog.csdn.net/zzzmmmkkk/article/details/4266888

 

现在进入主题——从代码层对几种排法的实现的分析:(对一些=取舍的测试)

#include<iostream>
using namespace std; 
int a[100];
void qsort(int, int);
void qsort_(int, int);
void qsort_t(int, int);
int n;
int main() {
	cin >> n;
	for(int i = 0; i < n; ++i) 
		cin >> a[i];
	qsort_(0, n-1);
	for(int i = 0; i < n; ++i)
		cout << a[i] << " ";
}


//mid取中间 
void qsort(int left, int right) {
	int mid = a[(left+right)/2]; //a[left+((right-left)>>1)]奇技淫巧的中间值l+(r-l)保证了右移的数始终是正数。 
	int i = left, j = right, temp;
	do{
		while(a[i] < mid) i++;//此处判断条件只能为'>' ,'<'号.
		while(a[j] > mid) j--;//否则像222111这样的序列就无操作。 
		if(i <= j)
		{ //如果去掉=,当i = j时此该条件下的执行语句i++/j--都无法执行,程序无法推进。 
			temp = a[i];
			a[i] = a[j];
			a[j] = temp;
			i++;//因此若要去掉 =号,可以把i++,j--均移到if语句后面。 
			j--;
		}
	}while(i <= j);//i++,j--在if内的情况,判断条件都必须有=,否则像序列12就会无限循环。
	if(left < j)	qsort(left, j);
	if(i < right)	qsort(i, right);

}
/*
考虑一个判断语句中=的取舍问题时,须看判断语句块中的执行语句对程序的运行和推进是否有影响。 
*/ 
//mid取中间优化 
void qsort_(int left, int right) {
	int mid = a[(left+right)/2];
	int i = left, j = right, temp;
	do{
		while(a[i] < mid) i++;
		while(a[j] > mid) j--;/
		if(i < j) { 
			temp = a[i];
			a[i] = a[j];
			a[j] = temp;
		}
		i++;
		j--;
	}while(i < j);
	if(left < j)	
		qsort(left, j);
	if(i < right)
		qsort(i, right);

}

//填坑法
void qsort_t(int l, int r) {
	if(l >= r)
		return;
	int i = l, j = r;
	int key = a[r];
	while(i < j) {
		while(i < j && a[i] <= key)
			i++;//此处比较数值与key大小必须是<=,不然a[i]==key的情况下,i不变就造成死循环。  
		a[j] = a[i];//若没有=,遇到1122这样(含等值的项)的序列在两个相等的数比较时会造成死循环 
		while(i < j && a[j] >= key)
			j--;
		a[i] = a[j];
	}
//	while(i <= j)//无论i与j用<还是<=来判断,需有不断在递进i与j的语句在执行。(代码程序无误的角度) 
//	{
//		while(a[i] < key)
//			i++;
//		if(i <= j)
//		{
//			a[j] = a[i];
//			j--;
//		}
//		while(a[j] > key)
//			j--;
//		if(i <= j)
//		{
//			a[i] = a[j];
//			i++;
//		}	
//			
//	}
	a[i] = key;
	qsort(i, r);
	qsort(l, i-1);
	return ; 
}

 

最后是最近学到的多关键词排序:

void qsort(int l, int r)//多关键字快排 
{
	int i = l, j = r, mid1 = b[(l+r)/2], mid2 = a[(l+r)/2], t;
	do
	{
		while(b[i] < mid1 || ((b[i] == mid1) && (a[i] < mid2)))
			i++;
		while(b[j] > mid1 || ((b[j] == mid1) && (a[j] > mid2)))
			j--;
		if(i <= j)
		{
			t = a[i];
			a[i] = a[j];
			a[j] = t;
			t = b[i];
			b[i] = b[j];
			b[j] = t;
			i++;
			j--;
		}
	}while(i <= j);
	if(l < j)
		qsort(l, j);
	if(i < r)
		qsort(i, r);
}

 

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页