2013-08-22 14:55:33

八大排序方法汇总(选择排序-简单选择排序、堆排序,插入排序-简单插入排序、shell排序,交换排序-冒泡排序、快速排序,归并排序,计数排序)。

插入排序还可以和折半查找相结合,提高查找插入位置的速度,也就是折半插入排序,此处没有给出这种方法的相应代码。

对排序算法,可从以下几个方面评价:

  1. 时间复杂度;
  2. 空间复杂度;
  3. 稳定性。

代码(测试暂未发现问题,欢迎交流指正!):

 #include <iostream>
#include <cassert>
#include <ctime>
#include <bitset>
using namespace std; typedef int DataType;
const int MaxSize = ;
const int SortCutOff = ; //产生在[lowBound,upperBound - 1]区间的随机数
int RandomIntGenerate(int lowBound, int upperBound)
{
return (lowBound + (RAND_MAX * rand() + rand()) % (upperBound - lowBound + ) );
} //数组显示
void DisplayArray(DataType array[],int len)
{
assert(NULL != array && len > ); for (int i = ;i < len;++i)
{
cout<<array[i]<<"\t";
}
cout<<endl;
} //简单选择排序
void SelectSort(DataType *unStorted,size_t n)
{
assert(NULL != unStorted && n > ); size_t i;
size_t j;
size_t minIndex = ; for (i= ;i < n - ;++i)
{
minIndex = i;
for (j = i + ;j < n;++j)
{
minIndex = unStorted[minIndex] < unStorted[j] ? minIndex : j;
} swap(unStorted[i],unStorted[minIndex]); //没有判断i与minIndex是否相等
}
} //简单插入排序
void InsertSort(DataType *unStorted,size_t n)
{
assert(NULL != unStorted && n > ); size_t i;
int j; //不能定义为size_t,因为for循环的结束条件需要将j减为-1作为结束条件
DataType dataToInsert = ; for (i= ;i < n - ;++i)
{
dataToInsert = unStorted[i + ];
for (j = i;j >= ;--j)
{
if (unStorted[j] > dataToInsert)
{
unStorted[j + ] = unStorted[j];
}
else
{
break;
}
}
unStorted[j + ] = dataToInsert; //注意此处为j + 1,而非j
}
} //插入排序-shell排序
//简单插入排序在输入为基本有序的情况下,性能最好,
//shell排序每次大步长下的排序,相当于通过分组对数组预处理,使其基本有序
void ShellSort(DataType *unStorted,size_t n)
{
assert(NULL != unStorted && n > ); size_t step = n / ;
size_t k;
size_t i;
int j; //不能定义为size_t,因为for循环的结束条件需要将j减为-1作为结束条件
DataType dataToInsert = ; while (step >= ) //n为1时,step为0,不进入while循环就返回;
{
for (k = ;k < step;++k )
{
for (i= ;i < n - step;i += step)
{
dataToInsert = unStorted[i + step];
for (j = i;j >= ;j -= step)
{
if (unStorted[j] > dataToInsert)
{
unStorted[j + step] = unStorted[j];
}
else
{
break;
}
}
unStorted[j + step] = dataToInsert; //注意此处为j + 1,而非j
}
}
step /= ;
}
} //交换排序-冒泡排序
void BubbleSort(DataType *unStorted,size_t n)
{
assert(NULL != unStorted && n > ); size_t i;
size_t j; for (i = n - ;i >= ;--i)
{
for (j = ;j < i;++j)
{
if (unStorted[j] > unStorted[j + ])
{
swap(unStorted[j],unStorted[j + ]);
}
}
}
} //快速排序的划分函数
size_t Partion(DataType *unStorted,size_t begin,size_t end)
{
assert(begin <= end); //begin end都是定义为size_t的,因此不需要检查 size_t i = begin;
size_t j = end;
//size_t pivot = i;
size_t pivot = RandomIntGenerate(begin,end); //枢轴为随机的,使得快速排序的划分尽可能对称
swap(unStorted[i],unStorted[pivot]); while (i < j)
{
while (j > i && unStorted[j] > unStorted[i])
{
--j;
} if (j > i)
{
swap(unStorted[i],unStorted[j]);
pivot = j;
++i;
} while (i < j && unStorted[i] < unStorted[j])
{
++i;
} if (j > i)
{
swap(unStorted[i],unStorted[j]);
pivot = i;
--j;
}
}
//return i;
//return j;
return pivot;
} //交换排序-快速排序
void QuickSort(DataType *unStorted,size_t begin,size_t end)
{
assert(NULL != unStorted); //assert(begin >= 0 && end >= 0); //begin end都是定义为size_t的,因此不需要检查 if (begin >= end)
{
return;
} int mid = Partion(unStorted,begin,end); if (begin < mid)
{
QuickSort(unStorted,begin,mid - );
} //QuickSort(unStorted,begin,mid - 1); //若mid为0,size_t类型的mid减1会出问题,因此用begin < mid判断
QuickSort(unStorted,mid + ,end);
} //归并两个数组
void Merge(DataType *unStorted,size_t begin,size_t mid,size_t end)
{
assert(NULL != unStorted);
assert(begin <= mid && mid <=end); DataType *resArray = new DataType[end - begin + ];
DataType *res = resArray; size_t lowIndex = begin;
size_t highIndex = mid + ; while (lowIndex <= mid && highIndex <= end)
{
if (unStorted[lowIndex] <= unStorted[highIndex])
{
*res++ = unStorted[lowIndex++];
}
else
{
*res++ = unStorted[highIndex++];
}
} while (lowIndex <= mid)
{
*res++ = unStorted[lowIndex++];
} while (highIndex <= end)
{
*res++ = unStorted[highIndex++];
} res = resArray; for (size_t index = begin;index <= end;++index)
{
unStorted[index] = *res++;
} delete [] resArray;
} //归并排序的非递归实现,自底向上归并
void MergeSortNonRecursive(DataType *unStorted,size_t n)
{
assert(NULL != unStorted); size_t begin = ;
size_t mid = ;
size_t end = ; size_t step = ; while (step < n)
{
begin = ;
mid = begin + step - ;
end = begin+ * step - ; while (mid < n)
{
end = end > (n - ) ? (n - ) : end; //防止end越界 Merge(unStorted,begin,mid,end); begin = end + ; //不是begin = begin + step + 1;
mid = begin + step - ;
end = begin+ * step - ;
}
step *= ;
}
} //归并排序的非递归实现,自顶向下归并,分治法
void MergeSort(DataType *unStorted,size_t begin,size_t end)
{
assert(NULL != unStorted); if (begin >= end)
{
return;
} size_t mid = begin + (end - begin) / ;
MergeSort(unStorted,begin,mid);
MergeSort(unStorted,mid + ,end); //若mid为size_t类型最大值,mid + 1就会越界,此时end已经越界
Merge(unStorted,begin,mid,end);
} //堆调整
//参数n为数组中最大小标,如数组有n+1个元素,最大下标为n
//posToAdjust为需要调整的位置的下标
void HeapAdjust(DataType *unStorted,size_t n,size_t posToAdjust)
{
assert(NULL != unStorted); //在调用的函数中已经有,可以删去 size_t lchildIndex = * posToAdjust + ;
size_t rchildIndex = * posToAdjust + ; size_t maxPosition = posToAdjust; //while (lchildIndex <= n || rchildIndex <= n)
while (lchildIndex <= n) //此处只要lchildIndex <= n ,即可进入循环
{
if (lchildIndex <= n && unStorted[lchildIndex] > unStorted[maxPosition])
{
maxPosition = lchildIndex;
}
//else if (rchildIndex <= n && unStorted[rchildIndex] > unStorted[maxPosition])
if (rchildIndex <= n && unStorted[rchildIndex] > unStorted[maxPosition]) //不是else if
{
maxPosition = rchildIndex;
} if (maxPosition != posToAdjust)
{
swap(unStorted[posToAdjust],unStorted[maxPosition]); posToAdjust = maxPosition; //更新posToAdjust,可以用递归,即HeapAdjust(unStorted,n,maxPosition);
lchildIndex = * maxPosition + ;
rchildIndex = * maxPosition + ;
}
else
{
break;
}
}
} //堆排序
//参数n为数组中最大小标,如数组有n+1个元素,最大下标为n
void HeapSort(DataType *unStorted,size_t n)
{
assert(NULL != unStorted); int index; for (index = (n - ) / ;index >= ;--index) //index需要减到0,因此不能定义为size_t
{
HeapAdjust(unStorted,n,index);
} for (index = n;index >= ;--index)
{
swap(unStorted[],unStorted[index]);
HeapAdjust(unStorted,index - ,); //不是HeapAdjust(unStorted,index,0);
}
} //计数排序,基本实现
//此处的基数排序的使用场合:
//输入为正数;
// 输入不重复;
//输入的最大数与输入的个数基本相等时空间利用率最高,也就是输入为0~n内的n个不重复的正数
void CountSortBasic_1(DataType *unStorted,size_t n)
{
assert(NULL != unStorted); size_t *hash = new size_t [n + ];
size_t cnt = ;
int index = ; for (index = ;index <= n;++index)
{
hash[index] = ;
} for (index = ;index < n;++index) //index < n而非index <= n,因为此处访问的是unStorted[index],最大下标为n-1
{
++hash[ unStorted[index] ];
} for (index = ;index <= n;++index)
{
if (hash[ index ] != ) //判断index是否出现
{
unStorted[cnt++ ] = index;
}
} delete [] hash;
} //计数排序,位图实现
void CountSort(DataType *unStorted,size_t n)
{
assert(NULL != unStorted); bitset<MaxSize> hash; size_t cnt = ;
int index = ; hash.reset(); for (index = ;index < n;++index) //index < n而非index <= n,因为此处访问的是unStorted[index],最大下标为n-1
{
hash.set(unStorted[index]);
} for (index = ;index <= n;++index)
{
if ( hash.test(index) )
{
unStorted[cnt++ ] = index;
}
}
} //测试“脚手架”
void TestSortDriver()
{
/*DataType *unsortedArray = new DataType[MaxSize];
size_t lengthOfUnsortedArray;*/
size_t programToTest; int MinRandomInt;
int MaxRandomInt;
size_t i;
int timeStart = ;
double timeCostAverage = ; //用于计数排序时的输入
DataType unsortedArray[]= {,,,,,,,,,};
size_t lengthOfUnsortedArray = ; cout<<"please enter the length Of UnsortedArray,MinRandomInt and MaxRandomInt :"<<endl;
cin>>lengthOfUnsortedArray>>MinRandomInt>>MaxRandomInt;
cout<<"please enter the identifier of the program to test (end with ctrl+z): "<<endl;
while (cin>>programToTest)
{
for (i = ;i < lengthOfUnsortedArray;++i) //准备待排序数组
{
unsortedArray[i] = RandomIntGenerate(MinRandomInt,MaxRandomInt);
} cout<<"the unsorted array is :"<<endl;
DisplayArray(unsortedArray,lengthOfUnsortedArray); timeStart = clock();
switch (programToTest)
{
case :
cout<<"Test SelectSort..."<<endl;
SelectSort(unsortedArray,lengthOfUnsortedArray);
break; case :
cout<<"Test InsertSort..."<<endl;
InsertSort(unsortedArray,lengthOfUnsortedArray);
break; case :
cout<<"Test ShellSort..."<<endl;
ShellSort(unsortedArray,lengthOfUnsortedArray);
break; case :
cout<<"Test BubbleSort..."<<endl;
BubbleSort(unsortedArray,lengthOfUnsortedArray);
break; case :
cout<<"Test QuickSort..."<<endl;
QuickSort(unsortedArray,,lengthOfUnsortedArray - );
break; case :
cout<<"Test HeapSort..."<<endl;
HeapSort(unsortedArray,lengthOfUnsortedArray - );
break; case :
cout<<"Test MergeSortNonRecursive..."<<endl;
MergeSortNonRecursive(unsortedArray,lengthOfUnsortedArray);
break; case :
cout<<"Test MergeSort..."<<endl;
MergeSort(unsortedArray,,lengthOfUnsortedArray - );
break; case :
cout<<"Test CountSort..."<<endl;
CountSort(unsortedArray,lengthOfUnsortedArray);
break; default:
break;
} timeCostAverage = 1e9 * ( clock() - timeStart ) / ( CLOCKS_PER_SEC * lengthOfUnsortedArray );
cout<<"the average time cost per data is : "<<timeCostAverage<<" ns"<<endl; for (i = ;i < lengthOfUnsortedArray - ;++i)
{
if (unsortedArray[i] > unsortedArray[i + ])
{
cout<<"sort bug i = "<<i<<endl;
}
} cout<<"the sorted array is :"<<endl;
DisplayArray(unsortedArray,lengthOfUnsortedArray); cout<<endl;
cout<<"please enter the identifier of the program to test (end with ctrl+z): "<<endl;
} //delete [] unsortedArray;
} int main()
{
TestSortDriver(); return ;
}

八大排序方法汇总(选择排序,插入排序-简单插入排序、shell排序,交换排序-冒泡排序、快速排序、堆排序,归并排序,计数排序)的更多相关文章

  1. 归并排序 & 计数排序 & 基数排序 & 冒泡排序 & 选择排序 ----> 内部排序性能比较

    2.3 归并排序 接口定义: int merge(void* data, int esize, int lpos, int dpos, int rpos, int (*compare)(const v ...

  2. Java实现堆排序和计数排序

    堆排序代码: 思想:每次都取堆顶的元素,将其放在序列最后面,然后将剩余的元素重新调整为最小堆,依次类推,最终得到排序的序列. import java.util.Arrays; /** * 思路:首先要 ...

  3. Python列表排序方法汇总,超详细!

    1. 修改原列表,不创建新列表的排序 1 a = [3, 2, 8, 4, 6] 2 print(id(a)) # 2180873605704 3 a.sort() # 默认升序 4 print(a) ...

  4. php排序方法之选择排序

    //选择排序法 $arr = array(3,55,45,2,67,76,6.7,-65,85,4); function selectSort($arr){ for ( $i=0; $i<cou ...

  5. python之八大排序方法

    一.插入排序 #-*- coding:utf-8 -*- ''' 描述 插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的.个数加一的有序数据,算法适用于少量数据的排序,时 ...

  6. java常见排序方法

    1.java常用排序方法 1) 选择排序         原理:a. 将数组中的每个元素,与第一个元素比较          如果这个元素小于第一个元素, 就将这个         两个元素交换.   ...

  7. 排序算法汇总(java实现,附源代码)

    整理系统的时候发现了原来写的各种算法的总结,看了一下,大吃一惊,那时候的我还如此用心,具体的算法,有的已经模糊甚至忘记了,看的时候就把内容整理出来,顺便在熟悉一下,以后需要的时候就可以直接过来摘抄了. ...

  8. Python实现十大经典排序算法(史上最简单)。

    十大排序算法(Python实现)一. 算法介绍及相关概念解读 算法分类十种常见排序算法可以分为两大类: 非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn), ...

  9. Python实现十大经典排序算法(史上最简单)

    十大排序算法(Python实现)一. 算法介绍及相关概念解读 算法分类十种常见排序算法可以分为两大类: 非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn), ...

随机推荐

  1. 隐藏内容_网络推广_seo中级视频教程详解

    课程背景:SEO(Search Engine Optimization),汉译为搜索引擎优化.搜索引擎优化是一种利用搜索引擎的搜索规则来提高目的网站在有关搜索引擎内的排名的方式.SEO目的理解是:为网 ...

  2. Kail安装Parallels tools

    今天在安装虚拟机里面安装kail,在安装虚拟机提供的tools时候提示没有权限,如图: 后面经过自己证实首先tools是挂载的cdrom,在这样挂载下是没有写权限的(类似于windows下面读取光盘光 ...

  3. CSS 中的 em单位

    em的对应的像素值如何计算,一言以蔽之:em就是倍数当前元素font-size的倍数,其结果就是当前字体的像素值乘以em的值,至于font-size来自何处?有两个来源:继承自父元素和通过CSS直接设 ...

  4. JS判断设备终端(PC,iPad,iPhone,android,winPhone)和浏览器

    JS判断设备终端(PC,iPad,iPhone,android,winPhone)和浏览器 var ua = navigator.userAgent; var browser = {}, weixin ...

  5. javascript 面向对象技术

    面向对象术语 对象 ECMA-262 把对象(object)定义为“属性的无序集合,每个属性存放一个原始值.对象或函数”.严格来说,这意味着对象是无特定顺序的值的数组. 尽管 ECMAScript 如 ...

  6. Node.js 【使用npm安装一些包失败之笔记】

    镜像使用方法(三种办法任意一种都能解决问题,建议使用第三种,将配置写死,下次用的时候配置还在): 1.通过config命令 npm config set registry https://regist ...

  7. jquery获得option的值(示例)

    jquery获得option的值和对option的操作. jQuery获取Select元素,并选择的Text和Value: 复制代码代码如下: $("#select_id").ch ...

  8. php截取字符串的实例代码(支持utf-8)

    分享下php中截取字符串的例子,支持utf-8格式. 1,截取字符串 <?php $string="2006年4月我又长大了一岁!"; echo substr($string ...

  9. Catalyst揭秘 Day7 SQL转为RDD的具体实现

    Catalyst揭秘 Day7 SQL转为RDD的具体实现 从技术角度,越底层和硬件偶尔越高,可动弹的空间越小,而越高层,可动用的智慧是更多.Catalyst就是个高层的智慧. Catalyst已经逐 ...

  10. 拉链法解决Hash节点冲突问题

    <?php /* * hash::拉链法解决hash节点存储冲突问题 * ::2014-07-02 * ::Small_Kind */ class small_hash { private $s ...