当前位置: 编程技术>c/c++/嵌入式
基于C++实现的各种内部排序算法汇总
来源: 互联网 发布时间:2014-10-27
本文导语: 提起排序算法相信大家都不陌生,或许很多人已经把它们记得滚瓜烂熟,甚至随时可以写出来。是的,这些都是最基本的算法。这里就把各种内部排序算法总结归纳了一下,包括插入排序(直接插入排序,折半插入排序,希尔...
提起排序算法相信大家都不陌生,或许很多人已经把它们记得滚瓜烂熟,甚至随时可以写出来。是的,这些都是最基本的算法。这里就把各种内部排序算法总结归纳了一下,包括插入排序(直接插入排序,折半插入排序,希尔排序)、交换排序(冒泡排序,快速排序)、选择排序(简单选择排序,堆排序)、2-路归并排序。(另:至于堆排序算法,前面已经有一篇文章针对堆排序的算法实现做了详细的描述)
C++实现代码如下:
/*************************************************************************
> File Name: sort.cpp
> Author: SongLee
************************************************************************/
#include
using namespace std;
typedef int ElementType;
/*
*
* 为了实现N个数的排序,将后面N-1个数依次插入到前面已排好的子序列中,
*假定刚开始第1个数是一个已排好序的子序列。经过N-1趟就能得到一个有序序列。
*****时间复杂度:最好情况O(n),最坏情况O(n^2),平均情况O(n^2).
*****空间复杂度:O(1)
*****稳定性:稳定
*/
void InsertSort(ElementType A[], int n)
{
int i,j;
ElementType temp; // 临时变量
for(i=1; i0 && A[j-1]>temp; --j)
A[j] = A[j-1];
A[j] = temp;
}
}
/*
*
* 与直接插入排序不同的是,折半插入排序不是边比较边移动,而是将比较和移
*动操作分离出来,即先折半查找出元素的待插入位置,然后再统一地移动待插入位
*置之后的所有元素。不难看出折半插入排序仅仅是减少了比较的次数。
*****时间复杂度:O(n^2)
*****空间复杂度:O(1)
*****稳定性:稳定
*/
void BinaryInsertSort(ElementType A[], int n)
{
int i, j, low, high, mid;
ElementType temp;
for(i=1; i=high+1; --j) // 统一后移
A[j+1] = A[j];
A[high+1] = temp; // 插入
}
}
/*
*
* 希尔排序通过比较相距一定间隔的元素,即形如L[i,i+d,i+2d,...i+kd]的序列
*然后缩小间距,再对各分组序列进行排序。直到只比较相邻元素的最后一趟排序为
*止,即最后的间距为1。希尔排序有时也叫做*缩小增量排序*
*****时间复杂度:依赖于增量序列的选择,但最坏情况才为O(N^2)
*****空间复杂度:O(1)
*****稳定性:不稳定
*/
void ShellSort(ElementType A[], int n)
{
int i, j, dk; // dk是增量
ElementType temp;
for(dk=n/2; dk>0; dk/=2) // 增量变化
{
for(i=dk; i=0 && A[j]>temp; j-=dk)
A[j+dk] = A[j]; // 后移
A[j+dk] = temp;
}
}
}
/*
*
* 冒泡排序的基本思想是从后往前(或从前往后)两两比较相邻元素的值,若为
*逆序,则交换它们,直到序列比较完。我们称它为一趟冒泡。每一趟冒泡都会将一
*个元素放置到其最终位置上。
*****时间复杂度:最好情况O(n),最坏情况O(n^2),平均情况O(n^2)
*****空间复杂度:O(1)
*****稳定性:稳定
*/
void BubbleSort(ElementType A[], int n)
{
for(int i=0; ii; --j) // 从后往前
{
if(A[j-1] > A[j])
{
flag = true;
// 交换
A[j-1] = A[j-1]^A[j];
A[j] = A[j-1]^A[j];
A[j-1] = A[j-1]^A[j];
}
}
if(flag == false)
return;
}
}
/*
*
* 快速排序是对冒泡排序的一种改进。其基本思想是基于分治法:在待排序表L[n]
*中任取一个元素pivot作为基准,通过一趟排序将序列划分为两部分L[1...K-1]和
*L[k+1...n],是的L[1...k-1]中的所有元素都小于pivot,而L[k+1...n]中所有元素
*都大于或等于pivot。则pivot放在了其最终位置L(k)上。然后,分别递归地对两个子
*序列重复上述过程,直至每部分内只有一个元素或空为止,即所有元素放在了其最终
*位置上。
*****时间复杂度:快排的运行时间与划分是否对称有关,最坏情况O(n^2),最好情况
*O(nlogn),平均情况为O(nlogn)
*****空间复杂度:由于需要递归工作栈,最坏情况为O(n),平均情况为O(logn)
*****稳定性:不稳定
*/
int Partition(ElementType A[], int low, int high)
{
// 划分操作有很多版本,这里就总以当前表中第一个元素作为枢纽/基准
ElementType pivot = A[low];
while(low < high)
{
while(low=pivot)
--high;
A[low] = A[high]; // 将比枢纽值小的元素移到左端
while(low