目录

一、排序的概念

二、排序的分类

三、交换排序(省略冒泡)

1、概念

2、算法思想

3、实现原理

4、快速排序代码

四、归并排序

1、概念

2、代码实现

五、堆排序

1、堆排序基本思想

2、代码实现

六、插入排序

1、概念

2、代码实现

七、基数排序

1、概述

2、代码实现


一、排序的概念

排序是计算机内经常进行的一种操作,其目的是将一组“无序”的记录序列调整为“有序”的记录序列。(递增或递减)

二、排序的分类

一图以蔽之:

三、交换排序(省略冒泡)

1、概念

快速排序:

又称划分交换排序(partition-exchange sort),简称快排,一种排序算法,最早由东尼·霍尔提出。在平均状况下,排序n个项目要 O(n log2 n)(大O符号)次比较。在最坏状况下则需要 O(n^2)次比较,但这种状况并不常见。事实上,快速排序 (n log n)通常明显比其他算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地达成。

——(维基百科)

快速排序:

分治排序的一种排序算法,它将一个数组分成两个子数组,将两个部分独立的排序。快速排序和归并排序是互补的,归并排序将数组分成两个子数组分别排序,并将有序的子数组归并以将整个数组排序,而快速排序则是就当两个子数组都有序时,整个数组就自然有序了。归并中,递归调用发生在处理整个数组之前,而在快速中,递归调用发生在处理整个数组之后

2、算法思想

快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

3、实现原理

(1)设置两个变量 low、high,排序开始时:low=0,high=size-1。

(2)整个数组找基准正确位置,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面

(a)默认数组的第一个数为基准数据,赋值给key,即key=array[low]。

(b)因为默认数组的第一个数为基准,所以从后面开始向前搜索(high–),找到第一个小于key的array[high],就将 array[high] 赋给 array[low],即 array[low] = array[high]。(循环条件是 array[high] >= key;结束时 array[high] < key)

(c)此时从前面开始向后搜索(low++),找到第一个大于key的array[low],就将 array[low] 赋给 array[high],即 array[high] = array[low]。(循环条件是 array[low] <= key;结束时 array[low] > key)

(d)循环 2-3 步骤,直到 low=high,该位置就是基准位置。

(e)把基准数据赋给当前位置。

(3)第一趟找到的基准位置,作为下一趟的分界点。

(4)递归调用(recursive)分界点前和分界点后的子数组排序,重复2.2、2.3、2.4的步骤。

(5)最终就会得到排序好的数组。

4、快速排序代码

#include<iostream>
using namespace std;void display(int* array, int size) {for (int i = 0; i < size; i++) {cout<<array[i];if(i!=size-1)cout<<" ";}cout<<endl;
}int getStandard(int array[], int i, int j) {/// 基准数据int key = array[i];/// i是low,j是high,整个大循环如果i==j就停止while (i < j) {/// 因为默认基准是从左边开始,所以从右边开始比较/// 当队尾的元素大于等于基准数据时,就一直向前挪动 j 指针while (i < j && array[j] >= key) {j--;}/// 当找到比 array[i] 小的时,就把后面的值 array[j] 赋给 坑if (i < j) {array[i] = array[j];}/// 当队首元素小于等于基准数据时,就一直向后挪动 i 指针while (i < j && array[i] <= key) {i++;}/// 当找到比 array[j] 大的时,就把前面的值 array[i] 赋给 新坑if (i < j) {array[j] = array[i];}}/// 跳出循环时 i 和 j 相等,此时的 i 或 j 就是 key 的正确索引位置/// 把基准数据赋给正确位置(基准数据的坑)array[i] = key;return i;
}void QuickSort(int array[], int low, int high) {/// 开始默认基准为 lowif (low < high) {/// 分段位置下标int standard = getStandard(array, low, high);/// 递归调用排序/// 左边排序QuickSort(array, low, standard - 1);/// 右边排序QuickSort(array, standard + 1, high);}
}/// 合并到一起的快速排序,与上面的是一样的
// void QuickSort(int array[], int low, int high) {
//     if (low < high) {
//         int i   = low;
//         int j   = high;
//         int key = array[i];
//         while (i < j) {
//             while (i < j && array[j] >= key) {
//                 j--;
//             }
//             if (i < j) {
//                 array[i] = array[j];
//             }
//             while (i < j && array[i] <= key) {
//                 i++;
//             }
//             if (i < j) {
//                 array[j] = array[i];
//             }
//         }
//         array[i] = key;
//         QuickSort(array, low, i - 1);
//         QuickSort(array, i + 1, high);
//     }
// }int main() {int array[] = {49, 38, 65, 97, 76, 13, 27, 49, 10};int size = sizeof(array) / sizeof(int);/// 打印数据cout<<size<<" \n";QuickSort(array, 0, size - 1);display(array, size);return 0;
}

四、归并排序

1、概念

归并排序是一种效率较高的排序方法,它分为拆分和合并两大部分,先拆后合。

所谓拆分,就是将一堆无序的数拆成单个,方便合并。

所谓合并,就是将拆分好的数按照排序规则再拼凑起来。

详细解释请看下图:

看完这幅图你应该明白了,归并排序原来就是将一堆数字分开,再合成有序的数列。其实,这就是分治的思想,将大问题化小问题,将每个最小的问题处理好,合并起来大问题也就处理好了。

2、代码实现

#include <iostream>
using namespace std;///每一趟合并
void merge(int* data,int* tmp,int left,int mid,int right){int i=left,j=mid+1;int k=left;while(i<=mid&&j<=right){if(data[i]<data[j])tmp[k++]=data[i++];elsetmp[k++]=data[j++];}while(i<=mid)tmp[k++]=data[i++];while(j<=right)tmp[k++]=data[j++];for(int i=left;i<=right;i++)data[i]=tmp[i];
}///拆
void Msort(int* data,int* tmp,int left,int right){if(left<right){int mid=(left+right)/2;Msort(data,tmp,left,mid);Msort(data,tmp,mid+1,right);merge(data,tmp,left,mid,right);}
}///归并排序入口
void msort(int* data,int n){int* tmp=new int[n];if(tmp){Msort(data,tmp,0,n-1);delete[] tmp;}
}int main() {int n;cin>>n;int* data=new int[n];for(int i=0;i<n;i++)cin>>data[i];for(int i=0;i<n;i++)cout<<data[i]<<" ";cout<<endl;///归并排序入口msort(data,n);for(int i=0;i<n;i++)cout<<data[i]<<" ";cout<<endl;return 0;
}/**
输入:
10
2 8 4 9 1 10 22 15 11 34
输出:
2 8 4 9 1 10 22 15 11 34
1 2 4 8 9 10 11 15 22 34
*/

五、堆排序

1、堆排序基本思想

(1)将待排序序列构造成一个大顶堆。

(2)此时,整个序列的最大值就是堆顶的根节点。

(3)将其与末尾元素进行交换, 此时末尾就为最大值。

(4)然后将剩余 n-1 个元素重新构造成一个堆, 这样会得到 n 个元素的次小值。 如此反复执行, 便能得到一个有序序列了。

最后可以看到在构建大顶堆的过程中, 元素的个数逐渐减少,最后就得到一个有序序列了。

注:一般升序采用大顶堆, 降序采用小顶堆。

2、代码实现

/**以大顶堆举例*/
#include<iostream>
using namespace std;void Max_heap(int arr[], int first, int last){int par = first;int son = par * 2 + 1;while(son <= last){if(son < last && arr[son] < arr[son + 1]){son++;}if(arr[par] > arr[son]){///如果满足,那么就直接返回return;}else{int temp = arr[par];arr[par] = arr[son];arr[son] = temp;///交换顺序par = son;son = par * 2 + 1;///再次进入循环}}
}void heap_sort(int arr[], int len){for(int i = len / 2 - 1;i >= 0;i--){///从最后一个非叶子节点开始往回走Max_heap(arr, i, len-1);}///先排好形成大顶堆///下面代码:先将第一个元素和已经排好元素前一位作交换,再进行堆排序for(int i = len - 1;i > 0;i--){int temp = arr[0];arr[0] = arr[i];arr[i] = temp;Max_heap(arr, 0, i - 1);}
}int main(){int n;///一共有多少数据cin>>n;int* arr=new int[n+1];///要排序的数据for(int i = 0;i < n;i++){cin>>arr[i];}heap_sort(arr, n);for(int i = 0;i < n;i++){cout<<arr[i]<<" ";}cout<<endl;delete[] arr;return 0;
}/**
输入:
6
9 2 4 23 10 1
输出:
1 2 4 9 10 23
*/

六、插入排序

1、概念

(1)直接插入排序
把待排序的数据插入到已经排好序的数据中,直到所有的数据插入完成,即就是直接插入排序。(如流行于陕西一带的纸牌游戏,挖坑)一般待排序的区间是第二个数到最后一个数。注意动态移动插入的过程,结合图与代码去理解。

例如下面的例子就是待排序区间从 7 到 8,把第一个数当作已经排序的数据:

(2)希尔排序

希尔排序实在前面直接插入排序的基础上进行改进的一种排序。直接插入排序的变量 i 其实就是一个间隔,而希尔排序的间隔不是 1,它的间隔逐渐缩小直到为 1 的一种排序(当间隔gap到达1时停止),因此又叫缩小增量法。它是对直接插入排序算法的优化,当间隔不为 1 的时候,都是预排序。下图是举例,第一次的间隔是数据长度的三分之一再加一。即 gap = size / 3 + 1

2、代码实现

#include <iostream>using namespace std;///初始化数组
void SetArray(int *data, int size) {//srand(time(0));cout << "随机初始化" << size << "个数" << endl;for (int i = 0; i < size; i++) {data[i] = rand() % 100 + 1;}
}///打印函数
void Print(int *data, int size) {for (int i = 0; i < size; i++) {cout << data[i] << " ";}cout << endl;
}///交换函数
void Swap(int &a, int &b) {int tmp = a;a = b;b = tmp;
}///冒泡排序
void Bubble_Sort(int *data, int size) {for (int i = size - 1; i >= 0; i--) {bool flag = false;        //、是否交换标志for (int j = 0; j < i; j++) {if (data[j + 1] < data[j]) {Swap(data[j], data[j + 1]);flag = true;//发生了交换}}if (flag == false) {//全程无交换break;}}
}///直接插入排序
void Insertion_Sort(int *data, int size) {for (int i = 1; i < size; i++) {int tmp = data[i];int j;for (j = i; j > 0 && data[j - 1] > tmp; j--) {///前一个数大于后一个树,进行交换data[j] = data[j - 1];}///找到合适位置,进行插入data[j] = tmp;}
}///折半插入排序
void Binary_Insertion_Sort(int *data, int size) {for (int i = 1; i < size; i++) {int low = 0, high = i - 1;//在i之前找到最佳位置int tmp = data[i], mid, j;while (low <= high) {//寻找最佳位置mid = (low + high) / 2;if (data[mid] < tmp) {//大于中间值,到右半部分寻找low = mid + 1;} else {//小于中间值,到左半部分寻找high = mid - 1;}}for (j = i; j > low; j--) {data[j] = data[j - 1];}data[j] = tmp;}
}///希尔排序(通俗易懂版)
void ShellInsert(int *arr, int len, int gap) {int k, i, j, temp;///k循环是处理每一组for (k = 0; k < gap; k++) {///i循环是调用了其中一组进行排序for (i = k; i < len; i += gap) {///temp是某组第i个数值(都是比较序列的最后一个)temp = arr[i];///k永远的每一组的第一个for (j = i; j > k; j -= gap) {///条件符合temp与arr[j]交换if (temp > arr[j - gap])arr[j] = arr[j - gap];elsebreak;}arr[j] = temp;}}
}///调用希尔排序,确定gap(gap大小是循环除以2)
void ShellSort(int *arr, int len) {int gap = len / 2;while (true) {ShellInsert(arr, len, gap);Print(arr, len);if (gap == 1)break;gap /= 2;}
}///改进版希尔排序
void Shell_sort(int *arr, int len) {int i, j, gap, key;///初始间隔:n/2,每一趟之后除以2for (gap = len / 2; gap > 0; gap /= 2) {///每一趟采用插入排序,为什么是i++而不是i+=gap呢,因为是每一组都处理一下for (i = gap; i < len; i++) {key = arr[i];for (j = i; j >= gap && key < arr[j - gap]; j -= gap)arr[j] = arr[j - gap];///找到合适位置,进行插入arr[j] = key;}Print(arr, len);}
}int main() {cout << "请输入数组长度:" << endl;int size, *data;cin >> size;data = new int[size];SetArray(data, size);cout << "冒泡排序前:" << endl;Print(data, size);cout << "冒泡排序后:" << endl;Bubble_Sort(data, size);Print(data, size);SetArray(data, size);cout << "直接插入排序前:" << endl;Print(data, size);cout << "直接插入排序后:" << endl;Insertion_Sort(data, size);Print(data, size);SetArray(data, size);cout << "折半插入排序前:" << endl;Print(data, size);cout << "折半插入排序后:" << endl;Binary_Insertion_Sort(data, size);Print(data, size);SetArray(data, size);cout << "希尔排序前:" << endl;Print(data, size);cout << "希尔排序后:" << endl;ShellSort(data, size);//Shell_sort(data,size);Print(data, size);return 0;
}

七、基数排序

1、概述

基数排序的知识点我就不贴出来,相信都能搜到对应概念解释,下面就直接上代码,代码解释其实也很清晰了。

2、代码实现

#include<iostream>
using namespace std;///补充:(arr[i] / exp) % 10  这个表达式很重要哦,作用是截取到某个数的某一位/// 获取数组arr中最大值,arr——待排序的数组,len——数组arr的长度。
int arrmax(int *arr, int len) {int i, imax;imax = arr[0];for (i = 1; i < len; i++)if (arr[i] > imax)imax = arr[i];return imax;
}/// 对数组arr按指数位进行排序。
/// arr——待排序的数组,len——数组arr的长度。
/// exp——排序指数,exp=1:按个位排序;exp=10:按十位排序;......
void _radixsort(int *arr, int len, int exp) {int i;int result[len];       /// 存放从桶中排序好收集到的数据的临时数组。int buckets[10] = {0};   /// 初始化10个桶。///遍历arr,将数据出现的次数存储在buckets中。for (i = 0; i < len; i++)buckets[(arr[i] / exp) % 10]++;///调整buckets各元素的值,调整后的值就是arr中元素在result中的位置。///核心是下面两行代码,我暂时不知道怎么解释。下面两行代码处理完后buckets的数字///代表的是该桶前面有多少个已经排好序的数for (i = 1; i < 10; i++)buckets[i] = buckets[i] + buckets[i - 1];/// 将arr中的元素填充到result中。注意:一定得是倒序从后面一个一个读取哦!///再说一遍,这里的倒序取非常关键!for (i = len - 1; i >= 0; i--) {int iexp = (arr[i] / exp) % 10;result[buckets[iexp] - 1] = arr[i];buckets[iexp]--;}/// 将排序好的数组result复制到数组arr中。///memcpy(arr, result, len * sizeof(int));for (int i = 0; i < len; i++)arr[i] = result[i];
}/// 基数排序主函数,arr——待排序的数组,len——数组arr的长度。
void radixsort(int *arr, int len) {int imax = arrmax(arr, len);    /// 获取数组arr中的最大值。int iexp;    /// 排序指数,iexp=1:按个位排序;iexp=10:按十位排序;....../// 从个位开始,对数组arr按指数位进行排序。for (iexp = 1; imax / iexp > 0; iexp = iexp * 10) {_radixsort(arr, len, iexp);int i;///cout << iexp << " ";     ///输出指数for (i = 0; i < len; i++)cout << arr[i] << " ";cout << endl;}
}int main() {///int arr[] = {144, 203, 738, 905, 347, 215, 836, 26, 527, 602, 946, 504, 219, 750, 848};///int len = sizeof(arr) / sizeof(int);int len;cin >> len;int *data = new int[len];for (int i = 0; i < len; i++)cin >> data[i];for (int i = 0; i < len; i++)cout << data[i] << " ";cout<<endl;radixsort(data, len);  /// 基数排序。/// 显示排序结果。cout<<"显示最后排完序的结果:"<<endl;for (int i = 0; i < len; i++)cout << data[i] << " ";cout << endl;return 0;
}/**
输入:
15
144 203 738 905 347 215 836 26 527 602 946 504 219 750 848
输出:
144 203 738 905 347 215 836 26 527 602 946 504 219 750 848
750 602 203 144 504 905 215 836 26 946 347 527 738 848 219
602 203 504 905 215 219 26 527 836 738 144 946 347 848 750
26 144 203 215 219 347 504 527 602 738 750 836 848 905 946
显示最后排完序的结果:
26 144 203 215 219 347 504 527 602 738 750 836 848 905 946
*/

我是花花,祝自己也祝您变强了~

数据结构——排序总结相关推荐

  1. 数据结构---排序算法的总结

    数据结构-排序算法的总结 分类 冒泡排序,时间复杂度O(n x n),空间复杂度O(1),稳定 简单选择排序,时间复杂度O(n x n),空间复杂度O(1),不稳定 希尔排序,时间复杂度O(n^1.3 ...

  2. 数据结构-排序基础代码

    数据结构-排序基础代码 1.快排的递归算法: void QuickSort(int A[],int n){Qsort(A,0,n-1); } void Qsort(int A[],int left,i ...

  3. 数据结构----排序

    ##数据结构--排序 Created with Raphaël 2.1.2选择选择直接选择直接选择堆排序堆排序直接选择堆排序大根堆.小根堆:找出最小(大)的Key Created with Rapha ...

  4. 【数据结构排序算法系列】数据结构八大排序算法

    排序算法在计算机应用中随处可见,如Windows操作系统的文件管理中会自动对用户创建的文件按照一定的规则排序(这个规则用户可以自定义,默认按照文件名排序)因此熟练掌握各种排序算法是非常重要的,本博客将 ...

  5. 数据结构-排序算法总结与感悟

    数据结构-排序算法总结 一,排序的基本概念 排序:有n个记录的序列{R1,R2,-,Rn},其相应关键字的序列是{K1,K2, -,Kn },相应的下标序列为1,2,-, n.通过排序,要求找出当前下 ...

  6. C++基础-介绍·数据结构·排序·算法

    C++基础-介绍·数据结构·排序·算法 特点 使用方向 RPC Data Struct 数据结构 栈 Stack 内存分配中的栈 队列 List 数组 Array 链表 LinkTable 树 Tre ...

  7. 数据结构-排序算法(c语言实现篇)

    数据结构-排序算法(c语言实现篇) 排序算法是非常常用的算法,从介绍排序的基本概念,到介绍各种排序算法的思想.实现方式以及效率分析.最后比较各种算法的优劣性和稳定性. 1 排序的概念及应用 1.1 排 ...

  8. 小孩的游戏 - 2021数据结构 排序和选择实验题

    小孩的游戏 - 2021数据结构 排序和选择实验题 pre 做都做了, 干脆发上来算了 : D 题目分析 算法与数据结构实验题 5.18 小孩的游戏 ★实验任务 一群小孩子在玩游戏,游戏规则是这样子, ...

  9. 数据结构排序算法实验报告_数据结构与算法-堆排序

    堆排序 堆排序是指利用堆这种数据结构所设计的一种排序算法.堆是一个近似完全二叉树的结构,并同时满足堆的性质:即子节点的键值或索引总是小于(或者大于)它的父节点,堆排序的时间复杂度为O(nlogn).( ...

  10. 20175330 数据结构-排序(选做)

    要求 在数据结构和算法中,排序是很重要的操作,要让一个类可以进行排序,有两种方法: 有类的源代码,针对某一成员变量排序,让类实现Comparable接口,调用Collection.sort(List) ...

最新文章

  1. CUBA Platform 7.0.4 发布,企业级应用开发平台
  2. Spring MVC 完整示例
  3. linux面向连接的协议,linuxTCP协议.ppt
  4. java catch 空指针异常_关于Java:捕获空指针异常
  5. java list按照某个字段排序_java相关:List对象去重和按照某个字段排序的实现方法...
  6. topcpder SRM 664 div2 A,B,C BearCheats , BearPlays equalPiles , BearSorts (映射)
  7. 编码utf-8的不可映射字符_建议永远不要在MySQL中使用UTF8
  8. C memset 踩坑
  9. C语言关键字 ISO/ANSI C90 C99 C11
  10. lnmp 0.4 安装指南
  11. 2020计算机大纲,计算机专业2020考试大纲.doc
  12. 服装关键点检测算法(CNN/STN)含(4点、6点以及8点)
  13. 计算机考研数据结构算法模板
  14. Build Settings发布设置
  15. 腾讯2017暑期实习编程题3
  16. matlab 响应曲面,MINITAB 响应曲面法应用
  17. 开网店应该如何不用自己发货呢?
  18. 【NLP】讯飞英文学术论文分类挑战赛Top10开源多方案–5 Bert 方案
  19. shell子串截取的三种用法:
  20. pd.diff()函数详解

热门文章

  1. 《软技能·代码之外的生存指南》读书笔记 ——理财
  2. 深度学习用于疾病预后-第二课第二周大作业-练习基于树和随机森林构建风险模型(强推,干货多)
  3. 班委竞选(离散数学课后习题 p45 29)
  4. Nginx热升级到1.23.4过程指导手册
  5. kubernetes-CNI网络插件
  6. 讨论:什么才算是真正的编程能力?
  7. Spring Web MVC(1)
  8. hdoj 1361 Parencodings 2001 Asia Regional Teheran
  9. ECNU 3263 丽娃河的狼人传说 (贪心)
  10. 当一位现代应用开发者与旧式系统开发者走进一家酒吧...