`
wq294948004
  • 浏览: 31571 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

排序算法

阅读更多
排序算法不仅要考虑效率,还要注意一个易被忽略的因素:稳定性(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),稳定的,将阵列分到有限数量的桶子里,每个桶子再个别排序(有可能再使用别的排序算法或是以递回方式继续使用桶排序进行排序)。

更多排序内容请参看维基百科
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics