快速排序
平均时间复杂度 O(NlogN)
最差时间复杂度O(N2)**
不稳定
<class KEY,class OTHER>
struct SET
{KEY key;//集合元素的标识,之后会根据标识来排序
OTHER other;//此处可以放结构体来储存其他信息
};
//划分函数的实现
//以第一个元素为划分元素,将从high到low的一个区间划分两半
template<class KEY,class OTHER>
void divide(SET<KEY,OTHER>a[],int low,int high)
{
//确定划分元素(此处默认首元素)
SET<KEY,OTHER>k=a[low];//注意不要写成a[0]
//这个划分函数的对象将是任意片段而非仅仅是原集合
while(high>low)//终止标志是二者下标箭头重合,high=low也不用排序了,只有一个元素
{
//开始划分,low指向k位置,可以算作k位置为空
//high指向末尾,从high开始与k比大小
//注意集合中选取key值,k也是结构体要选取key
while(high>low&&a[high].key>=k.key)high--;//high向前走直到找到一个比k小的元素停止
if(high>low) a[low]=a[high];//high位置元素(结构体直接移动)移动到low位置,high位置空出来
//向右移动low位置,找比k大的元素来填补high位置
while(high>low&&a[low].key<=k.key)low++;
if(high>low) a[high]=a[low];
//时刻注意确认high>low情况
//易错点:区分high/low是指向下标位置(始终顺序)的箭头,a[high].key与a[low].key是待排序的元素内容
}
//此时high=low
a[low].key=low;
return low;//返回中间位置
}
//快排的递归调用
template<class KEY,class OTHER>
void quickSort(SET<KEY,OTHER>a[],int low,int high)
{
if(low>=high) return;//递归终止
int mid=divide(a,low,high);//相当于在表中确定了mid位置,之后mid不用排序
quickSort(a,low,mid-1);
quickSort(a,mid+1,high);//递归分成左右半边
}
归并排序
时间复杂度O(NlogN)
空间复杂度O(N)
稳定,注意等于号
#include <iostream>
using namespace std;
//定义一个集合
template<class KEY,class OTHER>
struct SET
{KEY key;//集合元素的标识,之后会根据标识来排序
OTHER other;//此处可以放结构体来储存其他信息
};
//归并两个已经排好序的相邻序列
//然后元素一一对比,找两序列中较小的放新序列中
//mid是第一个序列结尾+1与第二个序列开头
template<class KEY,class OTHER>
void merge(SET<KEY,OTHER>a[],int low,int mid,int high)
{ //新建一个数组用来存放归并后的序列
SET<KEY,OTHER>*tmp=new SET<KEY,OTHER>[high-low+1];
int i=left,j=mid,k=0;//两个放在开头的箭头,来表示归并到哪个位置
//k专门看tmp走到哪里
while(i<mid&&j<=high)
{
if(a[i].key<=a[j].key) tmp[k++]=a[i++];//重视等于号,这让此算法稳定
else tmp[k++]=a[j++];
}//其中一个走到了尽头
//把还没走到尽头的依次填补到新序列中
while(i<mid) tmp[k++]=a[i++];
while(j<=high) tmp[k++]=a[j++];
//tmp毕竟是函数中暂时的,把它元素一一复制给a
for(int y=low;y<=high;y++) a[y++]=tmp[y++];
//收尾
delete[]tmp;
}
template<class OTHER,class KEY>
void mergeSort(SET<OTHER,KEY>a[],int low,int high)
{
if(low>=high) return;
int mid=(low+high)/2;
mergeSort(a,low,mid);//归并前半部分
mergeSort(a,mid+1,high);//归并后半部分
merge(a,low,mid+1,high);//注意这里mid+1,是后半部分第一个元素
}
基数排序
时间复杂度O(N)
#include <iostream>
using namespace std;
//基数排序对于每个口袋中元素采用单链表方式连接
//定义一个集合
template<class KEY,class OTHER>
struct SET
{KEY key;//集合元素的标识,之后会根据标识来排序
OTHER other;//此处可以放结构体来储存其他信息
};
template<class OTHER>
struct Node
{
Node*next;
SET<int,OTHER>data;//用int表示key值
Node(SET<int,OTHER>data1):data(data1){next=NULL;}
Node(){next=NULL;}
};
template <class OTHER>
void bucketSort(Node<OTHER>*&p)//直接传入链表头
{
Node<OTHER>*tail;
//先找到里面最大项判断位数
int max=0,len=0;
for(tail=p;tail!=NULL;tail=tail->next)//注意链表用在for中
{
if(tail->data.key>max)max=tail->data.key;
}
if(max==0)len=0;
else
{
while(max>0)
{max/=10;
len++;
}
}//确定位数
Node<OTHER>*bucket[10],*last[10];
int base=1;
//bucket[i]指向每个框,last[i]指向每个框中挂着的最后一个单链表
for(int i=0;i<len;i++)
{
for(int j=0;j<9;j++) bucket[j]=last[j]=NULL;//初始化框的指针、
while(p!=NULL)
{
int k=p->data/base%10;//取出每个p中数据base位数
if(bucket[k]==NULL) bucket[k]=last[k]=p;
else last[k]->next=p;
p=p->next;
}//把数按照最后一位分配到各个箩筐中
//接下来将各个箩筐连接起来(各箩筐内部最后一个单链表指向下一个箩筐开头)
for(int j=0;j<9;j++)
{
//考虑到一些箩筐中可能没有装
if(bucket[j]=NULL) continue;
//将第一个bucket与p连接起来
if(p==NULL) p=bucket[j];
else
{tail->next=bucket[j];}
tail=last[j];
}
tail->next=NULL;
base*=10;
}
}