1、快速排序
原理:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序。
void quickSort(int *a,int s,int t) //数组首地址a,数组起始位置s(初始值为0),结束位置t(初始值为n-1)
{
int i=s,j=t+1,temp,x=a[s];
do
{
do
{
i++;
} while (a[i]<a[s]); //找比第一个元素小的元素
do
{
j--;
} while (a[s]<a[j]); //找比第一个元素大的元素
if (i<j) //交换,将小的值放在左边,大的值放右边
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}while(i<j); //划分子区间的条件
a[s]=a[j]; //交换a[s]和a[j]的值,至此成功划分两个子区间
a[j]=x; //a[j]的位置确定下来
if(s<j-1)
quickSort(a,s,j-1); //递归排序左子区间
if (j+1<t)
quickSort(a,j+1,t); //递归排序右子区间
}
2、堆排序
原理:首先建立最大根堆,将根元素和根堆中最后一个元素调换,这样最后一个元素就排好序了,然后将剩余的元素更新为最大根堆,按照前面的方法,直至根堆中只剩下最后一个元素,排序完成。
void initHeap(int *data,int n) //初始化根堆
{
int t;
for (int i=(n-1)/2;i>=0;i--)
{
if (2*i+2<=n&&data[2*i+1]<data[2*i+2]) //左右子树比较,左子树存放较大值
{
t=data[2*i+1];
data[2*i+1]=data[2*i+2];
data[2*i+2]=t;
}
if (data[i]<data[2*i+1]) //左子树与父节点比较,父节点存放较大值
{
t=data[2*i+1];
data[2*i+1]=data[i];
data[i]=t;
}
}
}
void heapSort(int *data,int n) //堆排序
{
if (n<=0)
return; //递归终止条件
initHeap(data,n); //初始化根堆
int t=data[0]; //根与最后一个数值替换
data[0]=data[n];
data[n]=t;
heapSort(data,--n); //去掉最大值,继续递归
}
3、归并排序
原理:递归将待排序数组分割成n个部分,每部分只有1个元素,然后在递归将每2个部分元素进行排序,直至最后只剩下一个完整的部分,排序完成。
template<class T> void Merge(T a[],T TR[],int low,int mid,int high) //归并排序 a[low]~a[mid] 、a[mid]~a[high]
{
int i = low;
int j = mid + 1;
int k = 0;
while(i <= mid && j <= high)
{
if(a[i] < a[j])
TR[k++] = a[i++];
else
TR[k++] = a[j++];
}
while(i <= mid)
TR[k++] = a[i++];
while(j <= high)
TR[k++] = a[j++];
for(i = low; i <= high; i++) //将排序好的数据移回到原序列中
a[i] = TR[i - low];
}
template<class T> void MSort(T a[],T temp[],int low,int high)
{
if (low<high) //递归终止条件
{
int mid = (low + high) / 2; //进行分裂
MSort(a,temp,low,mid); //将前一半继续分裂
MSort(a,temp,mid + 1,high); //将后一半继续分裂
Merge(a,temp,low,mid,high); //进行归并排序
}
}
堆排序和快速排序都是不稳定的,而归并排序则是稳定的。
4、两个排好序的链表归并
pList mergeList(pList first,pList second)
{
pList out,p1,p2,pLast; //out为返回链表,p1指向first,p2指向second,pLast串联起两个链表
//first链表为空
if(first->next==NULL)
out=second;
//second链表为空
else if (second->next==NULL)
out=first;
//first和second都不为空
else
{
p1=first->next;
p2=second->next;
//first链表为返回链表
if (p1->data<=p2->data)
{
out=first;
pLast=p1; //pLast作用为串联这两个链表,指向返回链表的第一个节点
p1=p1->next;
}
//second链表为返回链表
else
{
out=second;
pLast=p2;
p2=p2->next;
}
while(p1!=NULL&&p2!=NULL)
{
if (p1->data<=p2->data)
{
pLast->next=p1; //pLast指向带返回的剩余节点
pLast=p1;
p1=p1->next;
}
else
{
pLast->next=p2;
pLast=p2;
p2=p2->next;
}
}
if (p1!=NULL)
pLast->next=p1;
if(p2!=NULL)
pLast->next=p2;
}
return out;
}
5、计数排序
计数排序算法针对待排序数组中的每个记录,扫描待排序的数组一趟,统计待排序数组中有多少个记录的值比该记录的值小。假设针对某一个记录,统计出的计数值为c,那么,这个记录在新的有序数组中的合适的存放位置即为c。
计数排序一般适用于输入数据是由一个小范围的数据构成,而且是利用空间换取了时间
//计数排序,输入数组src,输出数组dest,数组长度n,数组中最大元素k
void CountSort(const int *src,int *dest,int n,int k)
{
//c为计数数组,首先进行初始化
int *c=new int[k+1];
for(int i=0;i<k+1;i++)
c[i]=0;
//统计数组src中每个元素的个数
for (i=0;i<n;i++)
{
c[src[i]]+=1;
}
//累计统计个数,即src中每个元素前面有多少个元素
for (i=1;i<k+1;i++)
{
c[i]+=c[i-1];
}
//根据c中已知的src中每个元素前面有多少个元素,从大到小输出每个元素到dest数组
int j=0;
for (i=1; i<k+1;i++)
{
if (c[i]!=c[i-1])
{
j++;
dest[j-1]=i;
}
}
}