一,交换排序
冒泡排序(Bubble Sort)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
void bubbleSort(int *a,int len)
{
int i,j,change;
for(i=0;i<len;i++)
{
change=0;
for(j=len-1;j>i;j--)
{
if(a[j]<a[j-1])
{
change=1;
swap(&a[j],&a[j-1]);
}
}
if(!change)
break;
}
}
快速排序是由东尼·霍尔所发展的一种排序算法 基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
int partition(int *a,int s,int e)
{
int roll=a[s],i,j;
for(i=s+1,j=i;i<=e;i++)
{
if(a[i]<roll)
{
swap(&a[i],&a[j]);
j++;
}
}
swap(&a[s],&a[j-1]);
return j-1;
}
void quickSort(int *a, int start,int end)
{
if(start<=end)
{
int split=partition(a,start,end);
quickSort(a,start,split-1);
quickSort(a,split+1,end);
}
}
二,插入排序
直接插入排序(Insertion Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
void swap(int *p1, int *p2)
{
int temp;
temp=*p1;
*p1=*p2;
*p2=temp;
}
void insertSort(int *a,int len)
{
int i,j;
for(i=0;i<len;i++)
{
for(j=i+1;j>=1;j--)
{
if(a[j]<a[j-1])
swap(&a[j],&a[j-1]);
}
}
}
希尔排序,也称递减增量排序算法,是插入排序的一种高速而稳定的改进版本。它的基本思想是先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为dl的倍数的记录放在同一个组中。先在各组内进行直接插人排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。该方法实质上是一种分组插入方法。
void swap(int *p1, int *p2)
{
int temp;
temp=*p1;
*p1=*p2;
*p2=temp;
}
void shell(int *a,int d,int len)
{
int i,j;
for(i=d+1;i<len;i++)
{
for(j=i+d;j>=i && j<len;j--)
{
if(a[j]<a[j-d])
swap(&a[j],&a[j-d]);
}
}
}
void shellSort(int *a,int d,int len)
{
while(d>=1)
{
shell(a,d,len);
d=d/2;
}
}
三、选择排序
直接选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到排序序列末尾(目前已被排序的序列)。以此类推,直到所有元素均排序完毕。
void selectSort(int *a, int len)
{
int i,j,min,mark;
for(i=0;i<len;i++)
{
min=a[i];
for(j=i+1;j<len;j++)
{
if(a[j]<min)
{
min=a[j];
mark=j
}
}
if(min!=a[i])
swap(&a[i],&a[mark]);
}
}
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆性质:即子结点的键值或索引总是小于(或者大于)它的父节点(最大堆)
void shift(int *a,int r,int len)
{
int j,maxid;
for(j=r;j<=len/2;)
{
maxid=j;
if(2*j<len && a[2*j]>a[j])
maxid=2*j;
if(2*j+1<len && a[2*j+1]>a[maxid])
maxid=2*j+1;
if(maxid!=j)
{
swap(&a[maxid],&a[j]);
}
}
}
void buildHeap(int *a, int len) //为便宜计算 a的下标从1开始 构建大顶堆
{
int i;
for(i=len/2;i>0;i--)
shift(a,i,len);
}
void heapSort(int *a, int len)
{
int clen;
buildHeap(a,len);
swap(&a[1],&a[len]);
for(clen=len-1;clen>0;clen--)
{
shift(a,1,clen);
swap(&a[1],&a[clen]);
}
}
四、归并排序
归并排序(Merge sort,台湾译作:合并排序)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
算法描述
归并操作的过程如下:
- 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
- 设定两个指针,最初位置分别为两个已经排序序列的起始位置
- 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
- 重复步骤3直到某一指针达到序列尾
- 将另一序列剩下的所有元素直接复制到合并序列尾
{
if(start>mid || mid >end ) return;
int i=start,j=mid+1,k=0;
int *L=(int *)malloc((end-start+1)*sizeof(int));
while(i<=mid && j<=end)
{
if(a[i]<a[j])
{
L[k++]=a[i++];
}else
{
L[k++]=a[j++];
}
}
while(i<=mid)
L[k++]=a[i++];
while(j<=end)
L[k++]=a[j++];
for(i=start,j=0;i<=end;i++,j++)
{
a[i]=L[j];
}
free(L);
}
void mergeSort(int *a, int start,int end)
{
if(start<end)
{
int mid=(start+end)/2;
mergeSort(a,start,mid);
mergeSort(a,mid+1,end);
merge(a,start,mid,end);
}
}
五、基数排序
基数排序(Radix sort)是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。
struct DNode{
int data;
DNode *next;
}
struct Table
{
int id;
DNode *fisrt;
}
int digit(int num,int loc)
{
for(int i=1;i<loc;i++)
num/=10;
int res=num%10;
return res;
}
int maxCount(int *a,int len)
{
int max=0,n,num;
for(int i=0;i<len;i++)
{
n=0;
num=a[i];
while(num)
{
num/=10;
n++;
}
if(n>max) max=n;
}
return max;
}
void radixSort(int *a,int len)
{
int maxloc=maxcount(a,len);
DNode *ptemp;
Table *t=(Table *)malloc(10 * sizeof(Table));
for(int i=0;i<10;i++)
{
t[i]->id=i;
t[i]->first=NULL;
}
for(int j=1;j<maxcount;j++)
{
for(int k=0;k<len;k++)
{
int idm=digit(a[k],j);
DNode *p=t[idm]->first;
while(pt->next!=NULL) p=p->next;
DNode *d=(DNode *)malloc(sizeof(DNode));
d->data=a[k];
d->next=p->next;
p->next=d;
}
for(int i=0,k=0;i<=9;i++)
{
while(t[i]->first!=NULL)
{
a[k--]=t[i]->first->data;
ptemp=t[i]->first;
t[i]->first=t[i]->first->next;
free(ptemp);
}
}
}
}
六、计数排序
计数排序假设n个输入元素中的每一个都是介于0-k的整数,此处k为某个整数。计数排序顾名思义离不开计数,我们要计的是输入元素中相同元素出现的次数。对每一个输入元素x,确定小于x的元素的个数,那样排序之后,x在最终输出数组中的位置就可以确定了。例如:如果有17个元素小于x,则x就位于第18个输出的位置上。当然有几个元素相同时,这个方法就略微改进一下,因为不能将它们放在同一个位置上。
int countingSort(int *ar, int n, int k) {
int i, idx = 0;
int *B = calloc(k, sizeof(int));
for (i = 0; i < n; i++) {
B[ar[i]]++;
}
for (i = 0; i < k; i++) {
while (B[i]-- > 0) {
ar[idx++] = i;
}
}
free(B);
}