(代码基于linux环境,完整代码工程附下载链接,仅供学习,如有错误,欢迎指正。)
一、插入排序
插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。插入算法把要排序的数组分成两部分:第一部分包含已排好序的数,第二部分为未排好的,每次将未排序部分的第一个数插入到已排序部分合适的位置,直到第二部分没有数据。插入排序在数目较少时性能比较好。
/* 将未排序部分第一个数iValue插入到已排序数组[0,iCurrentCnt-1] */
static void insert_one(int *pArray, int iCurrentCnt, int iValue)
{
int iLoop0 = 0;
int iLoop1 = 0;
/* 找到插入位置 */
iLoop0 = iCurrentCnt;
while(iLoop0>0 && iValue<pArray[iLoop0-1])
{
iLoop0--;
}
/* 将插入位置后的数据后移一个数*/
for(iLoop1=iCurrentCnt; iLoop1>iLoop0; iLoop1--)
{
pArray[iLoop1] = pArray[iLoop1-1];
}
pArray[iLoop0] = iValue;
return;
}
/* pArray:待排序数组,iCnt:待排序数据数量*/
int insert_sort(int *pArray, int iCnt)
{
int iKey = 0;
int iLoop0 = 0;
for(iLoop0 = 1; iLoop0 < iCnt; iLoop0++)
{
iKey = pArray[iLoop0];
insert_one(pArray, iLoop0, iKey);
}
return 1;
}
二、归并排序
void merge(int *pArray, int p, int q, int r)
{
unsigned int sentinel = 99999999;//哨兵
int *pArrayl = NULL;
int *pArrayr = NULL;
int iLoop0 = 0;
int iLoop1 = 0;
int iLoop2 = 0;
pArrayl = (int *)malloc(sizeof(int)*(q-p+1));//sentinel card add 1
if (NULL == pArrayl)
{
printf("malloc pArrayl fail\n");
exit(0);
}
for(iLoop0 = 0; iLoop0 < q-p; iLoop0++)
{
pArrayl[iLoop0] = pArray[p+iLoop0];
}
pArrayl[q-p] = sentinel;
pArrayr = (int *)malloc(sizeof(int)*(r-q+1));//sentinel card add 1
if (NULL == pArrayr)
{
free(pArrayl);
printf("malloc pArrayr fail\n");
exit(0);
}
for(iLoop0 = 0; iLoop0 < r-q; iLoop0++)
{
pArrayr[iLoop0] = pArray[q+iLoop0];
}
pArrayr[r-q] = sentinel;
iLoop0 = 0;
iLoop1 = 0;
for(iLoop2 = p; iLoop2 < r; iLoop2++)
{
if(pArrayl[iLoop0] < pArrayr[iLoop1])
{
pArray[iLoop2] = pArrayl[iLoop0];
iLoop0++;
}
else
{
pArray[iLoop2] = pArrayr[iLoop1];
iLoop1++;
}
}
return;
}
int merge_sort(int *pArray, int p, int iCnt)
{
int q=0;
if (p<iCnt-1)
{
q = floor((p+iCnt)/2);
merge_sort(pArray, p, q);
merge_sort(pArray, q, iCnt);
merge(pArray, p, q, iCnt);
}
return;
}
三、堆排序
void Exchange(int *a, int *b)
{
int iTemp = 0;
iTemp = *a;
*a = *b;
*b = iTemp;
return;
}
void max_heapify(int *pArray, int i, int iCnt)
{
int l = 0;
int r = 0;
int largest = 0;
l = LEFT(i);
r = RIGHT(i);
//compare left
if (l <= iCnt && pArray[l-1] > pArray[i])
{
largest = l - 1;
}
else
{
largest = i;
}
//compare right
if (r <= iCnt && pArray[r-1] > pArray[largest])
{
largest = r - 1;
}
if (largest != i)
{
Exchange(&pArray[i], &pArray[largest]);
max_heapify(pArray, largest, iCnt);
}
return;
}
void build_max_heap(int *pArray, int iCnt)
{
int iLoop0 = 0;
int iLoopCnt = 0;
iLoopCnt = floor(iCnt/2);
for(iLoop0 = iLoopCnt; iLoop0 > 0; iLoop0--)
{
max_heapify(pArray, iLoop0-1, iCnt);
}
return;
}
int heap_sort(int *pArray, int iCnt)
{
int iLoop0 = 0;
int heapsize = iCnt;
build_max_heap(pArray, iCnt);
for(iLoop0 = 0; iLoop0 < iCnt - 1; iLoop0++)
{
Exchange(&pArray[0], &pArray[heapsize-1]);
heapsize -= 1;
max_heapify(pArray, 0, heapsize);
}
return;
}
四、快速排序
快速排序属于原地排序,时间复杂度O(nlgn),性能非常好。快速排序分两步,首先选择主元,把原数组分为两部分,前面的比主元小,后面比主元大,然后对两部分进行递归处理,递归完了也就是排好序的数组。下面代码实现主元选择数组的第一个元素,称为朴素的快速排序,当数组已经是正排序或逆排序为最坏情况,时间复杂度为O(n^2),类似插入排序。通常避免这种情况采用随机选择主元方法,采用随机数生成器产生主元。递归到后面的时候,待排序数比较少,可以不使用递归而使用其他排序,例如插入排序(在排序数目少时性能较好),这种优化叫做尾递归优化。
int partition(int *pArray, int p, int r)
{
int iLoop0 = 0;
int iLoop1 = p;
int iKey = 0;
iKey = pArray[r-1];
for(iLoop0 = p; iLoop0 < r-1; iLoop0++)
{
if (pArray[iLoop0] > iKey)
{
iLoop0++;
}
else
{
Exchange(&pArray[iLoop0], &pArray[iLoop1]);
iLoop1++;
}
}
Exchange(&pArray[iLoop1], &pArray[r-1]);
return iLoop1;
}
int quick_sort(int *pArray, int p, int iCnt)
{
int iLoop;
int iPartition;
if (p < iCnt-1)
{
iPartition = partition(pArray, p, iCnt);
quick_sort(pArray, p, iPartition);
quick_sort(pArray, iPartition+1, iCnt);
}
else
{
return 0;
}
}
五、冒泡排序
int bubble_sort(int *pArray, int iCnt)
{
int iLoop0 = 0;
int iLoop1 = 0;
for(iLoop0 = iCnt-1; iLoop0 > 0; iLoop0--)
{
for(iLoop1 = 0; iLoop1 < iLoop0; iLoop1++)
{
if (pArray[iLoop1] > pArray[iLoop1+1])
{
Exchange(&pArray[iLoop1], &pArray[iLoop1+1]);
}
}
}
}
代码及性能分析
cnt\time(s) | 插入排序 | 归并排序 | 堆排序 | 快速排序 | 冒泡排序 |
10 | 0.000002 | 0.000007 | 0.000002 | 0.000001 | 0.000001 |
100 | 0.000034 | 0.000042 | 0.000028 | 0.000016 | 0.000086 |
1000 | 0.002453 | 0.000411 | 0.000334 | 0.000182 | 0.007766 |
10000 | 0.223187 | 0.004761 | 0.004495 | 0.002339 | 0.761384 |
100000 | 22.025167 | 0.054158 | 0.058023 | 0.028551 | 76.286659 |
1000000 | 2199.23389 | 0.618193 | 0.845696 | 0.340799 | 7657.28906 |
代码下载:http://download.youkuaiyun.com/detail/dawan2008/5710221