效率比较
算法实现
◎冒泡排序
冒泡排序(英语:Bubble Sort)是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
冒泡排序算法流程如下:
- 比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
代码实现
void bubbleSort(int a[],int len)
{
int i, j, temp;
for (j=0; j<len; j++)
{
for (i=0; i<len-j; i++)
{
if (a[i] > a[i+1])
{
temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
}
}
}
}
◎快速排序
快速排序(英语:Quicksort),又称划分交换排序(partition-exchange sort),快速排序是对冒泡排序的一种改进,由C. A. R. Hoare在1962年提出。
快速排序算法流程如下:
- 从数列中挑出一个元素,称为"基准"(pivot)。
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
代码实现
/*
* 函数参数:
* a[]: 待排序数组
* start:数组起始下标
* end:数组末位下标
*/
void quickSort(int a[], int start, int end)
{
if(start >= end)
{
return ;
}
int low = start;
int high = end;
int key = a[start]; // 基准
while(low < high)
{
while(low < high && key <= a[high])
{
high--;
}
a[low] = a[high];
while(low < high && key >= a[low])
{
low++;
}
a[high] = a[low];
}
a[low] = key;
quickSort(a, start, low-1);
quickSort(a, low+1, end);
}
◎插入排序
插入排序(英语:Insertion Sort)是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
代码实现
void InsertSort(int a[],int len)
{
int i, j, temp;
for (i=0; i<len; i++)
{
j = i-1;
temp = a[i];
while (j>=0 && temp<a[j])
{
a[j+1] = a[j];
j--;
}
a[j+1] = temp;
}
}
◎希尔排序
希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。
希尔排序算法流程如下:
- 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序。
- 随着增量逐渐减小,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
代码实现
void shellSort(int a[], int len)
{
int i, j, temp;
int gap=0;
while (gap <= len) // 生成初始增量
{
gap = 3*gap + 1;
}
while (gap >= 1)
{
for (i=gap; i<len; i++)
{
j = i-gap;
temp = a[i];
while (j>=0 && a[j]>temp)
{
a[j+gap] = a[j];
j = j-gap;
}
a[j+gap] = temp;
}
gap = (gap-1) / 3; // 递减增量
}
}
◎选择排序
选择排序(Selection sort)是一种简单直观的排序算法。
选择排序算法流程如下:
- 在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
- 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
- 以此类推,直到所有元素均排序完毕。
代码实现
void selectSort(int a[], int len)
{
int i; // 有序区的末尾位置
int j; // 无序区的起始位置
int min; // 无序区中最小元素位置
int temp;
for (i=0; i<len; i++)
{
min=i;
for (j=i+1; j<len; j++)
{
if(a[j] < a[min])
min=j;
}
if (min != i)
{
temp = a[i];
a[i] = a[min];
a[min] = temp;
}
}
}
◎堆排序
堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。
堆排序算法流程如下:
- 将待排序的序列构造成一个大顶堆(或小顶堆)。
- 此时,整个序列的最大值就是堆顶的根结点。将它移走(就是将其与堆数组的末尾元素交换,此时末尾元素就是最大值)。
- 然后将剩余的n-1个序列重新构造成一个堆,这样就会得到n个元素中的次大值。
- 如此反复执行,便能得到一个有序序列了。
代码实现
/*
* parentIndex:父结点下标
* leftIndex: 左孩子结点下标
*/
// 调整大根堆
void adjustHeap(int a[], int parentIndex, int len)
{
int leftIndex, temp;
temp = a[parentIndex];
for (leftIndex=2*parentIndex; leftIndex<=len; leftIndex*=2)
{
if (leftIndex<len && a[leftIndex] < a[leftIndex+1])
{
leftIndex++;
}
if (temp > a[leftIndex])
{
break;
}
a[parentIndex] = a[leftIndex];
parentIndex = leftIndex;
}
a[parentIndex] = temp;
}
// 交换元素
void swap(int arr[], int i, int j)
{
int temp;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// 堆排序
void heapSort(int arr[],int len)
{
int index;
for (index=len/2 ; index>0; index--)
{
adjustHeap(arr, index, len);
}
for (index=len; index>1; index--)
{
// 交换堆顶元素与末尾元素
swap(arr, 1, index);
adjustHeap(arr, 1, index-1);
}
}
◎归并排序
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
归并排序算法流程如下:
- 将待排序数组递归的分解至最小,分成许多个左右子序列。
- 对每个子序列分别进行排序。
- 将已有序的子序列合并排序,使子序列段间有序,得到完全有序的序列。
代码实现
#include <stdio.h>
// 合并数组
void Merge(int sourceArr[],int tempArr[], int start, int mid, int end)
{
int i = start, j=mid+1, k = start;
while (i!=mid+1 && j!=end+1)
{
if (sourceArr[i] > sourceArr[j])
tempArr[k++] = sourceArr[j++];
else
tempArr[k++] = sourceArr[i++];
}
// 追加剩余元素
while (i != mid+1)
tempArr[k++] = sourceArr[i++];
while (j != end+1)
tempArr[k++] = sourceArr[j++];
for (i=start; i<=end; i++)
sourceArr[i] = tempArr[i];
}
// 归并排序
void MergeSort(int sourceArr[], int tempArr[], int start, int end)
{
int mid;
if(start < end)
{
mid = start + (end-start) / 2;
MergeSort(sourceArr, tempArr, start, mid);
MergeSort(sourceArr, tempArr, mid+1, end);
Merge(sourceArr, tempArr, start, mid, end);
}
}
// 打印数组
void printArray(int a[], int n)
{
int i;
for (i=0; i<n; i++)
{
printf("%3d", a[i]);
}
printf("\n");
}
void main()
{
int sourceArr[9] = {44,33,11,22,66,88,77,55,99};
int n = sizeof(sourceArr) / sizeof(int);
int tempArr[9];
printArray(sourceArr, n);
MergeSort(sourceArr, tempArr, 0, n-1);
printArray(tempArr, n);
}