排序的一些概念
排序的稳定性:
如果在序列中有两个数据元素 r[i] 和 r[j],它们的关键字 k[i]== k[j],且在排序之前,对象 r[i] 排在 r[j] 前面;
如果在排序之后,对象 r[i]仍在对象 r[j] 的前面,则称这个排序方法是稳定的,否则称这个排序方法是不稳定的。
排序的重要指标:
排序的时间复杂度
排序的空间复杂度
排序算法的可读性与可维护性
多关键字与单关键字的排序无本质区别,只是在第一关键字相同时,再去比较第二关键字继续排序,以此类推。
tip:
Sort类中都提供了Asc(bool类型)变量,可以选择(true)升序或降序(false)排序。默认为升序
因为待排序的对象不一定为基本类型,所以使用模板技术,可以对支持比较与交换的数据对象进行排序。
下面是交换函数(模板)。
template < typename T >
static void swap(T& a,T& b)
{
T c(a);
a = b;
b = c;
}
选择排序
选择排序的基本思想:
每次(例如第i次,i=0,1,…,n-2)从后面的n-i个待排数据元素中
选出最小(大)的元素,作为排序后的第i个元素
不多说,选择排序看代码应该就可以理解了,不理解就多看两遍。
/* 选择排序 O(n2)
不稳定排序
*/
template < typename T >
static void Select(T arr[],int len,bool ASC = true)
{
for(int i=0;i<len;i++)
{
int spe = i;
for(int j=i+1;j<len;j++)//找出最小的值
{
if(ASC ? (arr[spe] > arr[j]) : (arr[spe] < arr[j]) )
{
spe = j;
}
}
if(spe != i)
{
swap(arr[spe],arr[i]);
}
}
}
插入排序
插入排序的基本思想:
当插入第i(i>=1)个数据元素时,前面的V[0],V[1],…'V[i-1]已经排好序;
这时,用V[i]的关键字与V[i-1],V[i-2],…,V[0]的关键字进行比较,
找到位置后将V[i]插入,原来位置上的对象向后顺移。
流程简述:
0:(外围大循环 0-n)
1:拷贝当前待排序数据(待排序数据顺序为从前向后),向前比较
2:若比较成立(逆序),当前被比较数据向后顺移一位,记录当前下标,向前比较,重复2
3:若比较不成立,记录的下标与待排序数据的下标是否一致
4:不一致,将待排序数据插入至此
5:一致,不需要操作
/* 插入排序 O(n2)
稳定排序
*/
template < typename T >
static void Insert(T arr[],int len,bool ASC = true)
{
for(int i=1;i<len;i++)
{
int spe = i;
T e = arr[i];
for(int j=i-1;(j>=0)&&(ASC ? (e < arr[j]) : (e > arr[j]) );j--)
{
arr[j+1] = arr[j];
spe = j;
}
if(spe != i)
{
arr[spe] = e;
}
}
}
冒泡排序
冒泡排序的基本思想:
每次从后向前进行(假设第i次),j=n-1,n-2,…,i,
两两比较V[j-1]和V[j]的关键字;
如果发生逆序,则交换V[j-1]和V[j]
流程简述:
0:(外围大循环 0-n)
1:当前待排序数据(待排序数据顺序为从后向前)向前比较
2:若比较成立(逆序),当前被比较数据与待排序数据交换位置
3:若比较不成立,不需要操作
4:重复1
tip:
采用Exchange(bool类型)标记当前排序数据是否发生位置移动,如果没发生,说明数据已经排好序,可以提前结束排序操作,提高效率
/* 冒泡排序 O(n2)
稳定排序
*/
template < typename T >
static void Bubble(T arr[],int len,bool ASC = true)
{
bool exchange = true;
for(int i=0;(i<len) && exchange;i++)
{
exchange = false;
for(int j=len-1;j>i;j--)//找出最小的值
{
if(ASC ? (arr[j] < arr[j-1]) : (arr[j] > arr[j-1]) )
{
swap(arr[j],arr[j-1]);
exchange = true;
}
}
}
}