Collection of algorithm for sorting. 常见排序算法集(三) —— Quick Sort

Quick Sort

快排,一个排序方法能直接享受这样的名称殊荣,呵呵,可见其威力与重要性.

其中最重要的思想就是 “分治”—— divide and conquer !

这里排序用到的思想极其简单,却是很实用的!小孩子都会的简单想法.

先把所有数据分成三个部分. 在所有数据中选取某一元素X,比X小的放左边,比X大的放右边.

接着把这一思想同样分别施加在X元素的左边和右边部分,同样继续划分,选出一个元素X’ 比X‘小的放左边比X’大的放右边。

继续施加这种划分策略,直到划分的元素很少(实现的时候是选取的3为阈值),那么就对其进行简单排序(我这里选取的插入排序方法)。

整个算法就这么简单,漂亮!

想提一下,感觉《DSAA》里面的算法demo小点问题,数组会溢出,我已经测试过了,下面的代码实现是其修补改进.

只是参考了《算法导论》,实现的细节可能和算导略微不同.

quick_sort.h

#ifndef _QUICK_SORT_H
#define _QUICK_SORT_H
	#include <stdio.h>
	#include <stdlib.h>

	void swap(int* x,int* y);

	int median(int* array,int left,int right);

	void quick_sort(int* array,int left,int right);

	void Qsort(int* array,int size);

#endif

swap.c

交换 x,y 指向的值,这里用了一个小技巧 没有使用第三个变量(通常是tmp)交换两个数据的值.

/************************************************
code writer	:	EOF
code date	:	2014.09.20
code file	:	swap.c
e-mail		:	[email protected]

************************************************/
#include "quick_sort.h"

void swap(int* x,int* y)
{
	/*
	** Don't panic :)
	*/
	*y = *x - *y;

	*x = *x - *y;

	*y = *x + *y;
}

median.c

用于确保排序的不等关系式的条件 left < center < right

最后的hide pivot是把中间值和最右侧值交换, 便于比较以及数据的交换

/************************************************
code writer	:	EOF
code date	:	2014.09.20
code file	:	median.c
e-mail		:	[email protected]

************************************************/
int median(int* array,int left,int right)
{
	int center = (left+right)/2;

	if(array[left] > array[right])
	{
		swap(&array[left],&array[right]);
	}

	if(array[left] > array[center])
	{
		swap(&array[left],&array[center]);
	}

	if(array[center] > array[right])
	{
		swap(&array[center],&array[right]);
	}

	/*
	**	There are three if-statement here,
	** just make sure that :
	**	A[left] <= A[center] <= A[right]
	*/

	/*
	**	Hide pivot
	*/
	swap(&array[center],&array[right]);

	return array[right];
}

quick_sort.c 算法核心部分

/************************************************
code writer	:	EOF
code date	:	2014.09.20
code file	:	quick_sort.c
e-mail		:	[email protected]

************************************************/
#include "quick_sort.h"

#define CUT_OFF 3

void quick_sort(int* array,int left,int right)
{
	if(!array)
	{
		printf("You passed NULL into function %s()\n",__FUNCTION__);
		return;
	}

	if(left > right)
	{
		printf("Parameter @left and @right error! @left should less or equal to @right\n");
		return ;
	}

	int pivot = 0;
	int smaller_region_index = left;
	int bigger_region_index  = right-1;

	int tmp   = 0;
	int index = 0;
	int sentinel = 0;

	if(left + CUT_OFF <= right)
	{
		pivot = median(array,left,right);

		for(smaller_region_index -=1, bigger_region_index += 1;;)
		{
			while(array[++smaller_region_index] < pivot)
			{
				/*
				** DON'T do ++smaller_region_index here!
				** That must be hide a bug!
				*/
			}

			while(array[--bigger_region_index] > pivot)
			{
				/*
				** DON'T do --bigger_region_index here!
				** That must be hide a bug!
				*/
			}

			if(smaller_region_index < bigger_region_index)
			{
				swap(&array[smaller_region_index],&array[bigger_region_index]);
			}
			else
			{
				break;
			}

		}

		/*
		**	Restore pivot
		*/
		swap(&array[smaller_region_index],&array[right]);
		quick_sort(array,left,smaller_region_index-1);
		quick_sort(array,bigger_region_index+1,right);
	}
	else
	{
		/*
		**	Insertion sort.
		*/
		tmp 	= 0;
		index 	= 0;

		for(tmp = left; tmp <= right;tmp++)
		{
			sentinel = array[tmp];
			for(index = tmp;array[index-1] > sentinel &&  index > left;index--)
			{
				array[index] = array[index - 1];
			}
			array[index] = sentinel;
		}
	}
}

void Qsort(int* array,int size)
{
	quick_sort(array,0,size-1);
}

测试用程序:

Qsort_test.c

/************************************************
code writer	:	EOF
code date	:	2014.09.20
code file	:	Qsort_test.c
e-mail		:	[email protected]

************************************************/
#include "quick_sort.h"

int main()
{
	int array[] = {13,81,92,43,31,65,31,57,26,75,0};

	int size = sizeof(array)/sizeof(array[0]);
	int tmp = 0;

	Qsort(array,size);

	for(tmp = 0;tmp < size;tmp++)
	{
		printf("%4d",array[tmp]);
	}
	printf("\n");

	return 0;
}

灰暗的农庄 莱昂?奥古斯丁?莱尔米特 1844―1925年 法国 画布油画 1910年 85.10×71.10厘米

作为现实主义画派的领军人物,莱尔米特一生主要以农村为题材作画,并有幸成为这一杰出艺术流派的最后一位画家。莱尔米特生活的时代,正是法国的城市和农村的社会角色开始大变革的时期。整个国家正在迅速地现代化,城市也在加速实现工业化。文明、进步的北方和布满农庄和农民的南方,形成泾渭分明的态势,各大区之间几乎没有人口的流动。作为国际性大都会巴黎的居民,巴黎人开始把法国南部看成依旧保持原生态田园风情的乐土。生活在城市的巴黎精英们遂将城郊变成怀旧的天地,许多艺术家和作家也把这片土地当成创作的乐园。农民的形象依然是工业化前的社会生活的标志,于是我们就在这幅追忆性的图画中,看到了一个农民牵着他的牲畜,在周围一片寂静之中,独自彳亍前行。

时间: 2024-10-12 21:11:10

Collection of algorithm for sorting. 常见排序算法集(三) —— Quick Sort的相关文章

Collection of algorithm for sorting. 常见排序算法集(一)

Collection of algorithm for sorting (part one) 选择排序--Selection sort 可能你会觉得奇怪,为什么用结构体传参? 那是一层封装,我在面向对象的思想来写 : ) 对已一个数组,不管怎么操作,都不能越界. C语言 不会自动检查数组越界.这个时候程序员就应该负起责任来. 数组的边界成为数组必不可少的信息,此时可以把array当作一个对象来看,即此时的element. 我们排序的对象可能会变,比方说从int类型变到char类型,这时候我们仅仅

Collection of algorithm for sorting. 常见排序算法集(二)

Collection of algorithm for sorting heap sort 堆排序 The heapsort algorithm can be divided into two parts. In the first step, a heap is built out of the data. The heap is often placed in an array with the layout of a complete binary tree. The complete b

常见排序算法(三)

计数排序: 1.一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出,它的优势在于在对一定范围内的整数排序,   其时间复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法 2.步骤: a.找出给定整数序列的最大值 max 和最小值 min,创建大小为 max-min+1 的辅助空间,其值为 0 b.最小的那个数下标为 0,最大数下标为 -1,其他数 num 的下标为 num-min c.根据遍历所找到的数,在其相应下标处的值加一 d.遍历辅助空间,

排序算法之快速排序(Quick Sort) -- 适用于Leetcode 75 Sort Colors

Quick Sort使用了Divide and Concur的思想: 找一个基准数, 把小于基准数的数都放到基准数之前, 把大于基准数的数都放到基准数之后 Worst case: O(n^2) Average case: O(nlogN) 步骤: 初始的数组 Array a[]: 0 1 2 3 4 5 6 7 8 9 51 73 52 18 91 7 87 73 48 3 基准数: X = a[0] = 51 i 的值: i = 0 j 的值: j = 9 (a.length) Step 1:

几种常见排序算法

几种常见排序算法 几种常见排序算法 写在前面 基础介绍 初级排序算法 selection sort选择排序 insertion sort插入排序 ShellSort希尔排序 shuffing不是排序算法 merge sort归并排序 Abstract in-place merge原地归并的抽象方法 Top-down mergesort自顶向下的归并排序 Bottom-up mergesort自底向上的归并排序 quicksort 三向切分的快速排序 Heapsort堆排序 总结和比较 命题 本文

【整理】常见排序算法及其时间复杂度总结

原文出处: 1. 白话经典算法系列之八 MoreWindows白话经典算法之七大排序总结篇 2. 面试常用算法总结--排序算法(java版) 3. 常见排序算法小结 本篇主要整理了冒泡排序,直接插入排序,直接选择排序,希尔排序,归并排序,快速排序,堆排序七种常见算法,是从上面三篇博文中摘抄整理的,非原创. 一.冒泡排序 主要思路是: 通过交换相邻的两个数变成小数在前大数在后,这样每次遍历后,最大的数就"沉"到最后面了.重复N次即可以使数组有序. 冒泡排序改进1: 在某次遍历中,如果没有

常见排序算法(一) MergeSort

算法思想灰常重要,常见的用到分治思想的算法包括快速排序,归并,二分搜搜,大整数乘法等(参考 http://blog.csdn.net/com_stu_zhang/article/details/7233761,归纳很到位) 简单用归并对一个数组排序 思路: 简单来说对一个数组,只要他的左右两部分都是有序的,那么简单合并就ok了,那么左右两部分可以进一步划分各自的左右两部分----明显就是要递归了 算法:归并排序 1. 将数组一分为二,subArray1 和subArray2 2. 归并排序sub

常见排序算法(java实现)

常见排序算法介绍 冒泡排序 代码: public class BubbleSort { public static void sort(int[] array) { int tValue; for (int i = 0; i < array.length; i++) { for (int j = i; j < array.length; j++) { if (array[i] > array[j]) { tValue = array[i]; array[i] = array[j]; ar

常见排序算法(冒泡、选择、插入、快速、归并C++实现)

常见排序算法(冒泡.选择.插入.快速.归并C++实现) #include <iostream> using namespace std; // 冒泡排序 void bubbleSort (int data[], size_t size) { for (size_t i = 0; i < size - 1; ++i) { bool ordered = true; for (size_t j = 0; j < size - 1 - i; ++j) if (data[j+1] <