排序算法不仅要考虑效率,还要注意一个易被忽略的因素:稳定性(stable)。
Any comparison sort algorithm requires (nlogn) comparisons in the worst case.(decision tree)
一、插入排序(Insertion Sort),《算法导论》里那张摸牌的图解释的很形象。稳定的,时间复杂度为 O(n^2),而其他相同复杂度的排序算法几乎不用考虑。
二、希尔排序(Shell Sort),插入排序的增强版,但不是稳定的。需要注意gap的选择。
void shell_sort(int A[], int n)
{
int gap = n/2;
int i, j;
while (gap > 0) {
for (i = gap; i < n; i++) {
int tmp = A[i];
for (j = i - gap; A[j] > tmp; j -= gap)
A[j+gap] = A[j];
A[j+gap] = tmp;
}
gap /= 2;
}
}
三、合并排序(Merge Sort),分而治之的思想,稳定的,时间复杂度为 O(nlogn),但 merge() 需要额外的空间。觉得递归很漂亮,copy一下:
void merge_sort(int array[], int first, int last)
{
while (first < last) {
int mid = (first + last)/2;
merge_sort(array, first, mid);
merge_sort(array, mid+1, last);
merge(array, first, mid, last); // combine [first, mid] and [mid+1, last]
}
}
四、堆排序(Heapsort),利用一个数据结构最大堆(完全二叉树),根节点存放在数组位置1(
不能使用0!),不稳定的,时间复杂度为 O(nlogn)。这个算法很靓!
1. 生成一个最大堆,需要 from HEAP_SIZE/2 to 1 调用 max_heapify()
2. 排序过程中,交换第一个与最后一个后,再调用 max_heapify()
void max_heapify(int A[], int i, int heap_size)
{
int left = 2*i; // left_child(i);
int right = 2*i + 1; // right_child(i);
int largest = i;
if (left <= heap_size && A[left] > A[largest])
largest = left;
if (right <= heap_size && A[right] > A[largest])
largest = right;
if (largest != i) {
swap(&A[i], &A[largest]); // exchange
max_heapify(A, largest, int heap_size);
}
}
另外,优先级队列(Priority Queue)可以以堆排序为基础实现。
五、快速排序(Quicksort),也是分而治之的思想,不稳定的,时间复杂度为 O(nlogn)。这个算法的关键是 partition() 是否能使左右两边均衡。改进之处,可以用随机产生的元素作为 array[end]。
void quick_sort(int array[], int begin, int end)
{
if (begin < end) {
int p = partition(array, begin, end);
quick_sort(array, begin, p-1);
quick_sort(array, p+1, end);
}
}
int partition(int array[], int begin, int end)
{
int i = begin - 1;
int j = begin;
for ( ; j < end; j++) {
if (array[j] <= array[end]) {
i++;
swap(&array[i], &array[j]);
}
}
swap(&array[i+1], &array[end]);
return i + 1;
}
线性的非比较排序,我基本没用过。
六、计数排序(Counting Sort),稳定的,但需达到一定条件才能用。
如需排序数组A,需要用一个额外的数组C,C的长度是 max(A)-min(A)+1,C[i]表示与i相等的个数。
七、基数排序(Radix Sort),稳定的,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。
八、桶排序(Bucket Sort),稳定的,将阵列分到有限数量的桶子里,每个桶子再个别排序(有可能再使用别的排序算法或是以递回方式继续使用桶排序进行排序)。
更多排序内容请参看维基百科
分享到:
相关推荐
在本系统中,我们主要实现了五种常用的排序算法:冒泡排序法、快速排序法、直接插入排序法、折半插入排序法和树形选择排序法。这些算法都是在计算机科学中最基本和最重要的排序算法,广泛应用于各种数据处理和分析...
常见的经典排序算法有希尔排序、二分插入法、直接插入法、带哨兵的直接排序法、冒泡排序、选择排序、快速排序、堆排序等。 一、希尔排序(Shell 排序法) 希尔排序法,又称宿小增量排序,是 1959 年由 D.L.Shell ...
常见的排序算法有插入排序、快速排序、选择堆积排序法等。 插入排序算法是一种简单的排序算法,适用于小规模的数据结构。该算法将数据结构分成已排序部分和未排序部分,并将未排序部分的元素插入到已排序部分中。...
在计算机科学领域,排序算法是数据处理中的核心部分,它涉及到如何有效地重新排列一组数据,使其按照特定的顺序排列。本资源"总结了各种排序算法,并用C++代码实现,并有演示",提供了丰富的学习材料,包括不同类型...
希尔排序是一种基于插入排序的算法,通过将待排序的数组元素按某个增量分组,然后对每组使用直接插入排序算法排序。随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止...
本篇文章将介绍一种经典的排序算法——**合并排序法**(Merge Sort),并通过C语言实现该算法。合并排序是一种非常有效的排序方法,其核心思想是分治法:将数据分为若干个子集,对这些子集分别进行排序,最后将排序...