常见排序算法的总结与比较

 

1 冒泡排序

/*
作者:chenguolin
功能:测试冒泡排序的效率
日期:2013.01.10 22:01
*/
/*
1 冒泡排序(BubbleSort)的基本概念是:依次比较相邻的两个数,将小数放在前面,大数放在后面。
即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。
至此第一趟结束,将最大的数放到了最后。
在第二趟:仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2个数),将小数放前,
大数放后,一直比较到倒数第二个数(倒数第一的位置上已经是最大的),第二趟结束,在倒数第二的位置上得到一个新的最大数(其实在整个数列中是第二大的数)。
如此下去,重复以上过程,直至最终完成排序。

2 由于在排序过程中总是小数往前放,大数往后放,相当于气泡往上升,所以称作冒泡排序。

3 冒泡排序的时间复杂度为O(n^2),是一个稳定的排序算法
*/

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<ctime>
using namespace std;

const int MAXN = 100;
int arr[MAXN];

//冒泡排序主体
void bubbleSort(){
	for(int i = 0 ; i < MAXN-1 ; i++){
		for(int j = 0 ; j < MAXN-1-i ; j++){
		   if(arr[j] > arr[j+1])
			  swap(arr[j] , arr[j+1]);
		}
	}
}

//输出测试是否排序正确
void output(){
   for(int i = 0 ; i < MAXN ; i++)
	  cout<<arr[i]<<" ";
   cout<<endl;
}

int main(){
	//首先产生随机100000个数
    srand(time(0));
	for(int i = 0 ; i < MAXN ; i++){
	   int tmp = rand();
	   arr[i] = tmp;
	}

	clock_t star , end;
	star = clock();//开始测试
	bubbleSort();
	end = clock();//结束测试
	cout<<"Run time = "<<(end - star)<<endl;//输出几ms
	output();
	return 0;
}

 

2 插入排序

/*
作者:chenguolin
功能:测试插入排序的时间
日期:2013.01.10 22:33
*/

/*
1 假定这个数组的序是排好的,然后从头往后,如果有数比当前外层元素的值大,则将这个数的位置往后挪,直到当前外层元素的值大于或等于它前面的位置为止.
  这具算法在排完前k个数之后,可以保证a[1…k]是局部有序的,保证了插入过程的正确性.

2 插入排序的时间复杂度为O(n^2),是一个稳定的算法。
*/

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<ctime>
using namespace std;

const int MAXN = 100000;
int arr[MAXN];

//直接插入排序的主体
void insertSort(){
	for(int i = 1 ; i < MAXN ; i++){
		int tmp = arr[i];
		int j;
		for(j = i-1 ; j >= 0 ; j--){
			if(arr[j] > tmp)//只要比tmp大就往后移动一位
			  arr[j+1] = arr[j];
			else
			  break;
		}
		arr[j+1] = tmp;//j+1这位插入tmp
	}
}

//输出测试是否正确
void output(){
	for(int i = 0 ; i < MAXN ; i++)
	    cout<<arr[i]<<" ";
	cout<<endl;
}

int main(){
	srand(time(0));
	for(int i = 0 ; i < MAXN ; i++){
	   int tmp = rand();
	   arr[i] = tmp;
	}
	clock_t star , end;
	star = clock();
	insertSort();
	end = clock();
	cout<<"Run time = "<<(end-star)<<" ms"<<endl;
	output();
	return 0;
}

 

3 选择排序

/*
作者:chenguolin
功能:测试选择排序的时间效率
日期:2013.01.10  23:03
*/

/*
1 每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。 

2 选择排序的时间复杂度O(n^2) , 是不稳定的排序方法。
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<algorithm>
using namespace std;

const int MAXN = 100000;
int arr[MAXN];

//选择排序的主体
void selectSort(){
	for(int i = 0 ; i < MAXN-1 ; i++){
		int pos = i;
		for(int j = i+1 ; j < MAXN ; j++){
			if(arr[j] < arr[pos])
		       pos = j;
		}
		swap(arr[pos] , arr[i]);
	}
}

//输出测试数据是否排序正确
void output(){
	for(int i = 0 ; i < MAXN ; i++)
	    cout<<arr[i]<<" ";
	cout<<endl;
}

int main(){
   srand(time(0));
   for(int i = 0 ; i < MAXN ; i++){
       int tmp = rand();
       arr[i] = tmp;
   }
   clock_t star , end;
   star = clock();
   selectSort();
   end = clock();
   cout<<"Run time = "<<(end-star)<<" ms"<<endl;
   output();
   return 0;
}

 

4 快速排序

/*
作者:chenguolin
功能:测试快速排序的时间效率
日期:2013.01.10 23:45
*/

/*
1 它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,
  然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。 

2 快速排序是随机算法中平均最快的,时间复杂度为O(nLogn),有可能退化成O(n^2)。是一个不稳定的算法
int partition(int *arr, int l, int r){
	int pos = (l+r)>>1;//选择中间的数作为基准
	swap(arr[pos], arr[r]);//把这个数交换到最后一个位置
	int leftSeqNum = l; //左子序列的结束位置

	for(int i = l; i < r; i++){
		if(arr[i] < arr[r]){
		   if(leftSeqNum < i)
			   swap(arr[leftSeqNum], arr[i]);
		   leftSeqNum++;
		}
	}
	//再把基准的值交换到正确的位置
	swap(arr[leftSeqNum], arr[r]);
	return leftSeqNum;
}
void quickSort(int *arr, int l, int r){
    if(arr == NULL || l == r)
		return;
	int index = partition(arr, l, r);
	if(l < index)
		quickSort(arr, l, index-1);
	if(index < r)
		quickSort(arr, index+1, r);
}

 

5 归并排序

/*
作者:chenguolin
功能:测试归并排序的时间效率
日期:2013.01.11 0:00
*/

/*
1 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,
  每个子序列是有序的。然后再把有序子序列合并为整体有序序列
2 归并排序是一个不存在最好.最坏的情况的算法,算法的时间复杂度为O(nLogn)。是一个稳定的算法
*/

#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<algorithm>
using namespace std;

const int MAXN = 100000;
int arr[MAXN];
int tmpArr[MAXN];

//合并
void merge(int left , int mid , int right){
	int i , j , pos;
	i = left , j = mid+1 , pos = left;
	while(i <= mid && j <= right){
	     if(arr[i] <= arr[j])
			tmpArr[pos++] = arr[i++];
		 else
			tmpArr[pos++] = arr[j++];
	}
	while(i <= mid)
	     tmpArr[pos++] = arr[i++];
	while(j <= right)
	     tmpArr[pos++] = arr[j++];
    for(i = left ; i <= right ; i++)
	    arr[i] = tmpArr[i];
}

//两路-归并排序的主体
void mergeSort(int left , int right){
	if(left < right){
	   int mid = (left+right)>>1;
	   mergeSort(left , mid);
	   mergeSort(mid+1 , right);
	   merge(left , mid , right);//合并两部分
	}
}

//测试输出的数据是否正确
void output(){
    for(int i = 0 ; i < MAXN ; i++)
		cout<<arr[i]<<" ";
	cout<<endl;
}

int main(){
	srand(time(0));
	for(int i = 0 ; i < MAXN ; i++){
	    int tmp = rand();
		arr[i] = tmp;
	}
	clock_t star , end;
	star = clock();
	mergeSort(0 , MAXN-1);
	end = clock();
	cout<<"Run time = "<<(end-star)<<" ms"<<endl;
	output();
	getchar();
	return 0;
}
/*
Author: chenguolin
Date: 2014-02-24
*/

const int MAXN = 1010;
const int INF = 1<<30;

void merge(int *arr, int left, int mid, int right){
    int tmpLeft[MAXN];
    int tmpRight[MAXN];
    //copy to tmp arr
    for(int i = 1, j = left; i <= (mid-left+1); i++, j++)
        tmpLeft[i] = arr[j];
    for(int i = 1, j = mid+1; i <= (right-mid); i++, j++)
        tmpRight[i] = arr[j];
    tmpLeft[mid-left+1] = INF;
    tmpRight[right-mid] = INF;
    //merge two arr
    int l = 1, r = 1;
    for(int i = left; i <= right ; i++){
        if(tmpLeft[l] < tmpRight[r])
            arr[i] = tmpLeft[l++];
        else
            arr[i] = tmpRight[r++];
    }
}

void merge_sort(int *arr, int left, int right){
    if(left < right){
        int mid = (left+right)>>1;
        merge_sort(arr, left, mid);
        merge_sort(arr, mid+1, right);
        merge(arr, left, mid, right);
    }
}

int main(){
    return 0;
}

 

6 堆排序

/*
作者:chenguolin
功能:测试堆排序的时间效率
日期:2013.01.11 0:57
*/

/*
1 堆是一棵完全二叉树
2 堆排序首先是先把一个无序的序列整成一个最大堆,然后利用每次取出堆的“根节点+调整堆为最大堆”这种思路对一个序列排序
3 一个具有n个元素的数组,利用堆排序需要总共需要n次调整(第一次是调整为最大堆+排序的n-1调整)
4 堆排序的时间复杂度为O(nLogn),是一个不稳定的算法.
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<algorithm>
using namespace std;

const int MAXN = 100000+10;
const int N = MAXN-10;
int arr[MAXN];

//调整为最大堆
void adjustMaxHeap(int n , int size){
	int l_child , r_child , MAX;
	l_child = 2*n , r_child = 2*n+1 , MAX = n;
	if(l_child <= size && arr[l_child] > arr[MAX])
		MAX = l_child;
	if(r_child <= size && arr[r_child] > arr[MAX])
		MAX = r_child;
	if(MAX != n){//这里只有当MAX != n的时候才进行向下的调整,否则已经是最大或者到叶子节点不用调整
		swap(arr[n] , arr[MAX]);
	    adjustMaxHeap(MAX , size);
	}
}

//把无序序列建成一个最大堆
void initMaxHeap(){
    for(int i = N/2 ; i >= 1 ; i--)//从第一个非叶子节点n/2~1之间做n/2次调整
		adjustMaxHeap(i , N);
}

//堆排序
void heapSort(){
	int size = N;//size是实时的记录堆的元素个数
	for(int i = N ; i >= 2 ; i--){//如果是n个元素只要n-1次即可,当一个元素的时候就是最大不用做
	   swap(arr[i] , arr[1]);//把堆的根节点取出,把第i个元素换上去,这个时候size--就不会去调整到i了。
	   size--;
	   adjustMaxHeap(1 , size);//每次都要进行调整
	}
}

//测试输出数据是否正确
void output(){
	for(int i = 1 ; i <= N ; i++)
		cout<<arr[i]<<" ";
	cout<<endl;
}

int main(){
   srand(time(0));
   for(int i = 1 ; i <= N ; i++){
      int tmp = rand();
	  arr[i] = tmp;
   }
   clock_t star , end;
   star = clock();
   initMaxHeap();
   heapSort();
   end = clock();
   cout<<"Run time = "<<(end-star)<<" ms"<<endl;
   output();
   getchar();
   return 0;
}

 

 

 

 

 

 

 

时间: 2024-09-18 17:44:44

常见排序算法的总结与比较的相关文章

JavaScript版几种常见排序算法分享

说明 ·  每个浏览器测试得出的数据会不一样.比如我用chrome 测试 一般快速排序都会最快,IE 则根据数组长度有可能希尔最快. ·  不要用太大数据去测试冒泡排序(浏览器崩溃了我不管) 个人理解 ·  冒泡排序:最简单,也最慢,貌似长度小于7最优 ·  插入排序: 比冒泡快,比快速排序和希尔排序慢,较小数据有优势 ·  快速排序:这是一个非常快的排序方式,V8的sort方法就使用快速排序和插入排序的结合 ·  希尔排序:在非chrome下数组长度小于1000,希尔排序比快速更快 ·  系统

php实现的常见排序算法汇总_php技巧

本文汇总了常见的php排序算法,在进行算法设计的时候有不错的借鉴价值.现分享给大家供参考之用.具体如下: 一.插入排序 用文字简单的描述,比如说$arr = array(4,2,4,6,3,6,1,7,9); 这样的一组数字进行顺序排序: 那么,首先,拿数组的第二个元素和第一元素比较,假如第一个元素大于第二元素,那么就让两者位置互换,接下来,拿数组的第三个元素,分别和第二个,第一个元素比较,假如第三个元素小,那么就互换.依次类推.这就是插入排序,它的时间频度是:1+2+...+(n-1)=(n^

Javascript中的常见排序算法_javascript技巧

具体代码及比较如下所示: 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  <html xmlns="http://www.w3.org/1999/xhtml" lang="gb2312">

Java实现几种常见排序算法代码_java

稳定度(稳定性)一个排序算法是稳定的,就是当有两个相等记录的关键字R和S,且在原本的列表中R出现在S之前,在排序过的列表中R也将会是在S之前. 排序算法分类 常见的有插入(插入排序/希尔排序).交换(冒泡排序/快速排序).选择(选择排序).合并(归并排序)等. 一.插入排序 插入排序(Insertion Sort),它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入.插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),

JavaScript中几种常见排序算法小结_javascript技巧

说明 写这个主要是为了锻炼自己,并无实际意义. 每个浏览器测试得出的数据会不一样.比如我用chrome 测试 一般快速排序都会最快,IE 则根据数组长度有可能希尔最快. 不要用太大数据去测试冒泡排序(浏览器崩溃了我不管) 如果有兴趣可以 下载测试页面 个人理解 冒泡排序:最简单,也最慢,貌似长度小于7最优 插入排序: 比冒泡快,比快速排序和希尔排序慢,较小数据有优势 快速排序:这是一个非常快的排序方式,V8的sort方法就使用快速排序和插入排序的结合 希尔排序:在非chrome下数组长度小于10

php实现的常见排序算法汇总

 一.插入排序 用文字简单的描述,比如说$arr = array(4,2,4,6,3,6,1,7,9); 这样的一组数字进行顺序排序: 那么,首先,拿数组的第二个元素和第一元素比较,假如第一个元素大于第二元素,那么就让两者位置互换,接下来,拿数组的第三个元素,分别和第二个,第一个元素比较,假如第三个元素小,那么就互换.依次类推.这就是插入排序,它的时间频度是:1+2+...+(n-1)=(n^2)/2.则它的时间复杂度为O(n^2). php实现代码如下: 01 <?php 02 functio

排序算法总结

1.冒泡排序 冒泡排序是一种简单的排序方法,算法如下: 1. 首先将所有待排序的数字放入工作列表中. 2. 从列表的第一个数字到倒数第二个数字,逐个检查:若某一位上的数字大于他的下一位,则将它与它的下一位交换. 3. 重复2号步骤(倒数的数字加1.例如:第一次到倒数第二个数字,第二次到倒数第三个数字,依此类推...),直至再也不能交换. 用C语言实现如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 int BubbleSort(int *a, int n)    //

常用排序算法比较与分析

 一.常用排序算法简述 下面主要从排序算法的基本概念.原理出发,分别从算法的时间复杂度.空间复杂度.算法的稳定性和速度等方面进行分析比较.依据待排序的问题大小(记录数量 n)的不同,排序过程中需要的存储器空间也不同,由此将排序算法分为两大类:[内排序].[外排序]. 内排序:指排序时数据元素全部存放在计算机的随机存储器RAM中. 外排序:待排序记录的数量很大,以致内存一次不能容纳全部记录,在排序过程中还需要对外存进行访问的排序过程. 先了解一下常见排序算法的分类关系(见图1-1) 图1-1 常见

常见的五类排序算法图解和实现(多关键字排序:基数排序以及各个排序算法的总结)

基数排序思想 完全不同于以前的排序算法,可以说,基数排序也叫做多关键字排序,基数排序是一种借助"多关键字排序"的思想来实现"单关键字排序"的内部排序算法. 两种方式: 1.最高位优先,先按照最高位排成若干子序列,再对子序列按照次高位排序 2.最低位优先:不必分子序列,每次排序全体元素都参与,不比较,而是通过分配+收集的方式. 多关键字排序 例:将下表所示的学生成绩单按数学成绩的等级由高到低排序,数学成绩相同的学生再按英语成绩的高低等级排序.        第一个关键