C++实现八个常用的排序算法 插入排序、冒泡排序、选择排序、希尔排序等

本文实现了八个常用的排序算法:插入排序、冒泡排序、选择排序、希尔排序 、快速排序、归并排序、堆排序和LST基数排序

首先是算法实现文件Sort.h,代码如下:

/*
* 实现了八个常用的排序算法:插入排序、冒泡排序、选择排序、希尔排序
* 以及快速排序、归并排序、堆排序和LST基数排序
* @author gkh178
*/
#include <iostream> 

template<class T>
void swap_value(T &a, T &b)
{
 T temp = a;
 a = b;
 b = temp;
} 

//插入排序:时间复杂度o(n^2)
template<class T>
void insert_sort(T a[], int n)
{
 for (int i = 1; i < n; ++i)
 {
 T temp = a[i];
 int j = i - 1;
 while (j >= 0 && a[j] > temp)
 {
 a[j + 1] = a[j];
 --j;
 }
 a[j + 1] = temp;
 }
} 

//冒泡排序:时间复杂度o(n^2)
template<class T>
void bubble_sort(T a[], int n)
{
 for (int i = n - 1; i > 0; --i)
 {
 for (int j = 0; j < i; ++j)
 {
 if (a[j] > a[j + 1])
 {
 swap_value(a[j], a[j + 1]);
 }
 }
 }
} 

//选择排序:时间复杂度o(n^2)
template<class T>
void select_sort(T a[], int n)
{
 for (int i = 0; i < n - 1; ++i)
 {
 T min = a[i];
 int index = i;
 for (int j = i + 1; j < n; ++j)
 {
 if (a[j] < min)
 {
 min = a[j];
 index = j;
 }
 }
 a[index] = a[i];
 a[i] = min;
 }
} 

//希尔排序:时间复杂度介于o(n^2)和o(nlgn)之间
template<class T>
void shell_sort(T a[], int n)
{
 for (int gap = n / 2; gap >= 1; gap /= 2)
 {
 for (int i = gap; i < n; ++i)
 {
 T temp = a[i];
 int j = i - gap;
 while (j >= 0 && a[j] > temp)
 {
 a[j + gap] = a[j];
 j -= gap;
 }
 a[j + gap] = temp;
 }
 }
} 

//快速排序:时间复杂度o(nlgn)
template<class T>
void quick_sort(T a[], int n)
{
 _quick_sort(a, 0, n - 1);
}
template<class T>
void _quick_sort(T a[], int left, int right)
{
 if (left < right)
 {
 int q = _partition(a, left, right);
 _quick_sort(a, left, q - 1);
 _quick_sort(a, q + 1, right);
 }
}
template<class T>
int _partition(T a[], int left, int right)
{
 T pivot = a[left];
 while (left < right)
 {
 while (left < right && a[right] >= pivot)
 {
 --right;
 }
 a[left] = a[right];
 while (left < right && a[left] <= pivot)
 {
 ++left;
 }
 a[right] = a[left];
 }
 a[left] = pivot;
 return left;
} 

//归并排序:时间复杂度o(nlgn)
template<class T>
void merge_sort(T a[], int n)
{
 _merge_sort(a, 0, n - 1);
}
template<class T>
void _merge_sort(T a[], int left, int right)
{
 if (left < right)
 {
 int mid = left + (right - left) / 2;
 _merge_sort(a, left, mid);
 _merge_sort(a, mid + 1, right);
 _merge(a, left, mid, right);
 }
}
template<class T>
void _merge(T a[], int left, int mid, int right)
{
 int length = right - left + 1;
 T *newA = new T[length];
 for (int i = 0, j = left; i <= length - 1; ++i, ++j)
 {
 *(newA + i) = a[j];
 }
 int i = 0;
 int j = mid - left + 1;
 int k = left;
 for (; i <= mid - left && j <= length - 1; ++k)
 {
 if (*(newA + i) < *(newA + j))
 {
 a[k] = *(newA + i);
 ++i;
 }
 else
 {
 a[k] = *(newA + j);
 ++j;
 }
 }
 while (i <= mid - left)
 {
 a[k++] = *(newA + i);
 ++i;
 }
 while (j <= right - left)
 {
 a[k++] = *(newA + j);
 ++j;
 }
 delete newA;
} 

//堆排序:时间复杂度o(nlgn)
template<class T>
void heap_sort(T a[], int n)
{
 built_max_heap(a, n);//建立初始大根堆
 //交换首尾元素,并对交换后排除尾元素的数组进行一次上调整
 for (int i = n - 1; i >= 1; --i)
 {
 swap_value(a[0], a[i]);
 up_adjust(a, i);
 }
}
//建立一个长度为n的大根堆
template<class T>
void built_max_heap(T a[], int n)
{
 up_adjust(a, n);
}
//对长度为n的数组进行一次上调整
template<class T>
void up_adjust(T a[], int n)
{
 //对每个带有子女节点的元素遍历处理,从后到根节点位置
 for (int i = n / 2; i >= 1; --i)
 {
 adjust_node(a, n, i);
 }
}
//调整序号为i的节点的值
template<class T>
void adjust_node(T a[], int n, int i)
{
 //节点有左右孩子
 if (2 * i + 1 <= n)
 {
 //右孩子的值大于节点的值,交换它们
 if (a[2 * i] > a[i - 1])
 {
 swap_value(a[2 * i], a[i - 1]);
 }
 //左孩子的值大于节点的值,交换它们
 if (a[2 * i - 1] > a[i - 1])
 {
 swap_value(a[2 * i - 1], a[i - 1]);
 }
 //对节点的左右孩子的根节点进行调整
 adjust_node(a, n, 2 * i);
 adjust_node(a, n, 2 * i + 1);
 }
 //节点只有左孩子,为最后一个有左右孩子的节点
 else if (2 * i == n)
 {
 //左孩子的值大于节点的值,交换它们
 if (a[2 * i - 1] > a[i - 1])
 {
 swap_value(a[2 * i - 1], a[i - 1]);
 }
 }
} 

//基数排序的时间复杂度为o(distance(n+radix)),distance为位数,n为数组个数,radix为基数
//本方法是用LST方法进行基数排序,MST方法不包含在内
//其中参数radix为基数,一般为10;distance表示待排序的数组的数字最长的位数;n为数组的长度
template<class T>
void lst_radix_sort(T a[], int n, int radix, int distance)
{
 T* newA = new T[n];//用于暂存数组
 int* count = new int[radix];//用于计数排序,保存的是当前位的值为0 到 radix-1的元素出现的的个数
 int divide = 1;
 //从倒数第一位处理到第一位
 for (int i = 0; i < distance; ++i)
 {
 //待排数组拷贝到newA数组中
 for (int j = 0; j < n; ++j)
 {
 *(newA + j) = a[j];
 }
 //将计数数组置0
 for (int j = 0; j < radix; ++j)
 {
 *(count + j) = 0;
 }
 for (int j = 0; j < n; ++j)
 {
 int radixKey = (*(newA + j) / divide) % radix; //得到数组元素的当前处理位的值
 (*(count + radixKey))++;
 }
 //此时count[]中每个元素保存的是radixKey位出现的次数
 //计算每个radixKey在数组中的结束位置,位置序号范围为1-n
 for (int j = 1; j < radix; ++j)
 {
 *(count + j) = *(count + j) + *(count + j - 1);
 }
 //运用计数排序的原理实现一次排序,排序后的数组输出到a[]
 for (int j = n - 1; j >= 0; --j)
 {
 int radixKey = (*(newA + j) / divide) % radix;
 a[*(count + radixKey) - 1] = newA[j];
 --(*(count + radixKey));
 }
 divide = divide * radix;
 }
}

然后是测试文件main.cpp,代码如下:

#include "Sort.h"
using namespace std; 

template<class T>
void printArray(T a[], int n)
{
 for (int i = 0; i < n; ++i)
 {
 cout << a[i] << " ";
 }
 cout << endl;
} 

int main()
{
 for (int i = 1; i <= 8; ++i)
 {
 int arr[] = { 45, 38, 26, 77, 128, 38, 25, 444, 61, 153, 9999, 1012, 43, 128 };
 switch (i)
 {
 case 1:
 insert_sort(arr, sizeof(arr) / sizeof(arr[0]));
 break;
 case 2:
 bubble_sort(arr, sizeof(arr) / sizeof(arr[0]));
 break;
 case 3:
 select_sort(arr, sizeof(arr) / sizeof(arr[0]));
 break;
 case 4:
 shell_sort(arr, sizeof(arr) / sizeof(arr[0]));
 break;
 case 5:
 quick_sort(arr, sizeof(arr) / sizeof(arr[0]));
 break;
 case 6:
 merge_sort(arr, sizeof(arr) / sizeof(arr[0]));
 break;
 case 7:
 heap_sort(arr, sizeof(arr) / sizeof(arr[0]));
 break;
 case 8:
 lst_radix_sort(arr, sizeof(arr) / sizeof(arr[0]), 10, 4);
 break;
 default:
 break;
 }
 printArray(arr, sizeof(arr) / sizeof(arr[0]));
 }
 return 0;
}

最后是运行结果图,如下:

以上就是C++实现八个常用的排序算法的全部代码,希望大家对C++排序算法有更进一步的了解。

(0)

相关推荐

  • C++实现希尔排序算法实例

    目录 1.代码模板 2.算法介绍 3.实例 1.代码模板 // 希尔排序(Shell Sort) void ShellSort(SqList *L) { int i, j; int increment = L->length; // 先让增量初始化为序列的长度 do { increment = increment / 3 + 1; // 计算增量的值 for (i = increment + 1; i <= L->length; i ++ ) { if (L->arr[i] <

  • C++实现希尔排序(ShellSort)

    本文实例为大家分享了C++实现希尔排序的具体代码,供大家参考,具体内容如下 一.思路: 希尔排序:又称缩小增量排序,是一种改进的插入排序算法,是不稳定的. 设排序元素序列有n个元素,首先取一个整数gap<n作为间隔,将全部元素分为gap个子序列,所有距离为gap的元素放在同一个子序列中,在每一个子序列中分别施行直接插入排序.然后缩小间隔gap,重复上述的子序列和排序工作. 二.实现程序: #include <iostream> using namespace std; const int

  • C++实现简单的希尔排序Shell Sort实例

    本文以实例形式讲述了基于C++实现简单的希尔排序Shell Sort的方法,是一个很经典的算法,具体实现代码如下: #include <iostream> using namespace std; void ShellSort(int* iArray,int length) { //初始化jump等于length int jump = length; //标记本趟检测是否进行了交换, // 若进行了 则还有下次从头开始的检测, // 否则停止,继续改变jump的值 做另一趟排序 bool is

  • C++ 算法之希尔排序详解及实例

    C++ 算法之希尔排序算法详解及实例 希尔排序算法 定义: 希尔排序是插入排序的一种,也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本. 算法思想: 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序,随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰好被分为一组,算法终止. 时间复杂度: O(N) 空间复杂度: O(1) 性能: 希尔排序为不稳定算法(一次插入排序是稳定的,不会改变相同元素的相对顺序,但是在不同的插入排序中,相同的元素可能在各自的

  • Java实现的各种排序算法(插入排序、选择排序算法、冒泡排序算法)

    一.插入排序算法实现java版本 public static int[] insert_sort(int[] a) { for (int i = 0; i < a.length; i++) { for(int j=i+1;j>0&&j<a.length;j--) { if(a[j]<a[j-1]) { int tmp = a[j]; //这样定义初始化逻辑上是可以的,j变量,每次tmp的值变化的 a[j] = a[j-1]; a[j-1] = tmp; } } }

  • Java各种排序算法汇总(冒泡,选择,归并,希尔及堆排序等)

    本文实例汇总了Java各种排序算法.分享给大家供大家参考,具体如下: 1. 冒泡排序: public class SortTest { public static void main(String[] args) { int[] a = {345,7,32,5,4,-1,3,12,23,110,45645,321,456,78,-1,78,78,32,444,345}; show(a); bubbleSort(a); show(a); } private static void bubbleSo

  • PHP排序算法之简单选择排序(Simple Selection Sort)实例分析

    本文实例讲述了PHP排序算法之简单选择排序(Simple Selection Sort).分享给大家供大家参考,具体如下: 基本思想: 通过 n - i 次关键字间的比较,从 n - i + 1 个记录中选出关键字最小的记录,并和第 i (1 <= i <= n) 个记录交换,执行n-1趟 后就完成了记录序列的排序. 算法实现: <?php //简单选择排序 //交换函数 function swap(array &$arr,$a,$b){ $temp = $arr[$a]; $a

  • PHP排序算法之冒泡排序(Bubble Sort)实现方法详解

    本文实例讲述了PHP排序算法之冒泡排序(Bubble Sort)实现方法.分享给大家供大家参考,具体如下: 基本思想: 冒泡排序是一种交换排序,它的基本思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止. 最简单排序实现: 我们先来看看在没有学习各种排序方法前经常使用的排序方法(至少我是这样....): //这里使用了类型提示(type hint) array,不熟悉或者不习惯的同学大可去掉,不影响运算结果 function MySort(array &$arr){ $le

  • TypeScript实现十大排序算法之冒泡排序示例详解

    目录 一. 冒泡排序的定义 二. 冒泡排序的流程 三. 冒泡排序的图解 四. 冒泡排序的代码 五. 冒泡排序的时间复杂度 六. 冒泡排序的总结 一. 冒泡排序的定义 冒泡排序是一种简单的排序方法. 基本思路是通过两两比较相邻的元素并交换它们的位置,从而使整个序列按照顺序排列. 该算法一趟排序后,最大值总是会移到数组最后面,那么接下来就不用再考虑这个最大值. 一直重复这样的操作,最终就可以得到排序完成的数组. 这种算法是稳定的,即相等元素的相对位置不会发生变化. 而且在最坏情况下,时间复杂度为O(

  • java数据结构排序算法之树形选择排序详解

    本文实例讲述了java数据结构排序算法之树形选择排序.分享给大家供大家参考,具体如下: 这里我们就来说说选择类排序之一的排序:树形选择排序 在简单选择排序中,每次的比较都没有用到上次比较的结果,所以比较操作的时间复杂度是O(N^2),想要降低比较的次数,则需要把比较过程中的大小关系保存下来.树形选择排序是对简单选择排序的改进. 树形选择排序:又称锦标赛排序(Tournament Sort),是一种按照锦标赛的思想进行选择排序的方法.首先对n个记录的关键字进行两两比较,然后在n/2个较小者之间再进

  • Java排序算法总结之选择排序

    本文实例讲述了Java排序算法总结之选择排序.分享给大家供大家参考.具体分析如下: 选择排序的基本操作就是每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完.算法不稳定,O(1)的额外的空间,比较的时间复杂度为O(n^2),交换的时间复杂度为O(n),并不是自适应的.在大多数情况下都不推荐使用.只有在希望减少交换次数的情况下可以用.   基本思想   n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果: ①初始状态:

  • C语言排序算法之冒泡排序实现方法【改进版】

    本文实例讲述了C语言排序算法之冒泡排序实现方法.分享给大家供大家参考,具体如下: 冒泡排序和改进的冒泡排序 /*------------------------------------------------------------------------------------------- Bubble_sort.h 冒泡排序: 时间复杂度为O(N^2) 改进的冒泡排序: 时间复杂度仍为O(N^2) 一般的冒泡排序方法有可能会在已经排好序的情况下继续比较,改进的冒泡排序 设置了一个哨兵fla

  • java排序算法之_选择排序(实例讲解)

    选择排序是一种非常简单的排序算法,从字面意思我们就可以知道,选择就是从未排序好的序列中选择出最小(最大)的元素,然后与第 i 趟排序的第 i-1(数组中下标从 0 开始) 个位置的元素进行交换,第 i 个元素之前的序列就是已经排序好的序列.整个排序过程只需要遍历 n-1 趟便可排好,最后一个元素自动为最大(最小)值. 举个小例子: arr[] = {3,1,2,6,5,4} 第 1 趟排序: index = 0, min = 1, 交换后 -->  1,3,2,6,5,4 第 2 趟排序: in

  • 经典排序算法之冒泡排序(Bubble sort)代码

    经典排序算法 - 冒泡排序Bubble sort 原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换, 这样一趟过去后,最大或最小的数字被交换到了最后一位, 然后再从头开始进行两两比较交换,直到倒数第二位时结束,其余类似看例子 例子为从小到大排序, 原始待排序数组| 6 | 2 | 4 | 1 | 5 | 9 | 第一趟排序(外循环) 第一次两两比较6 > 2交换(内循环) 交换前状态| 6 | 2 | 4 | 1 | 5 | 9 | 交换后状态| 2 | 6 | 4 | 1

随机推荐