【排序算法】——冒泡排序、选择排序、插入排序、Shell排序等排序原理及Java实现
排序
1.定义:
所谓排序,即是整理文件中的内容,使其按照关键字递增或递减的顺序进行排列。
输入:n个记录,n1,n2……,其对应1的关键字为k1,k2……
输出:n(i1),n(i2)……,使得k(i1)<=k(i2)……
(形象点讲就是排排坐,调座位,高在前低在后;或者低在前高在后)
2.排序算法的评价的专业术语
(1)稳定性
稳定:在排序的文件中,若存在多个关键字相同的记录,经过排序后,这些具有相同
关键字的记录之间的相对顺序不会发生改变。
不稳定:若具有相同关键字记录之间的相对次序发生改变,则成为不稳定的排序算法。
(2)复杂度
时间复杂度:一个算法执行所需消耗的时间。
空间复杂度:运行完该程序所需要的内存大小
(3)排序方式
内排序:在排序过程中,整个文件放在内存中进行处理,不涉及数据的内外存交换。
(适用于记录个数不是很多的小文件)
外排序:排序过程中要进行数据的内、外存交换。
(适用于记录个数多,不能将其一次性放入内存中的大文件)
交换排序
思想:对排序记录的关键字进行两两比较,发现次序相反时则进行交换直至没有次序相反的记录。
主要排序方法:冒泡排序、选择排序
冒泡排序
(1)算法描述:
冒泡排序是一种简单的排序,每次访问要排序的数组序列,一次比较相邻两个元素的大小,
若顺序错误就进行交换。(这个方法名的由来是小的元素慢慢“浮”在数组顶端,也可称为沉底(大的元素))
(2)算法的实现
a.比较相邻的两个元素大小,如果第一个大于第二个元素的大小就进行交换
b.对每一对相邻的元素都进行同样的操作,从第一对到最后一对,经过此步骤
最大的元素将是最后的元素。
c.针对所有的元素重复上述操作,除过最后一个。
d.重复a-c步骤,直至排序完成
1 /**
2 *@Description: 排序算法
3 *@Author: dyy
4 */
5 public class Sort {
6 public static void main(String[] args) {
7 int [] arr = new int[]{4,2,1,6,3,6,0,-5,1,1};
8 bubbleSort(arr);
9 //遍历打印排序后的数组![image](https://note.youdao.com/favicon.ico)
10 for(int i = 0; i < arr.length;i++){
11 System.out.print(arr[i]+" ");
12 }
13 }
14 /**
15 *冒泡排序
16 * @date: 2018/8/15 11:27
17 */
18 public static void bubbleSort(int[] array){
19 //对数组进行临界判断
20 if(array==null||array.length==0){
21 System.out.println("array is NULL");
22 }
23 for(int i = 0; i < array.length - 1; i++){
24 //进行相邻元素额大小比较(也可循环至array.length-1,
25 // 循环至array.length-i-1是因为没经过一圈的排序后面的元素则就是有序的)
26 for(int j = 0;j < array.length-i-1;j++){
27 if(array[j]>array[j+1]){
28 swap(array,j,j+1);
29 }
30 }
31 }
32 }
33 /**
34 *实现数组中两个数的交换
35 * target为要交换的数组,x,y为要交换数字的下标
36 * @date: 2018/8/15 11:30
37 */
38 public static void swap(int[] target,int x,int y){
39 int temp = target[x];
40 target[x] = target[y];
41 target[y] = temp;
42 }
43 }
选择排序
(1)算法描述:选择排序是一种简单直观的排序算法。
它的工作原理是首先在未排序的序列中找到最大(小)的元素放置序列起始位置。
再从未排序序列中继续寻找元素放置已排序序列的尾部直至所有元素都有序。
(2)算法的实现:
a.初始状态:R[1……n]无序,有序数组为空
b.经过第i次扫描:R[1……i-1]有序,R[i……n]无序
c.经过n-1趟排序,为有序序列
1 /**
2 *选择排序
3 * @date: 2018/8/15 12:26
4 */
5 public static void selectSort(int[] array){
6 //临界条件判断
7 if(array==null||array.length==0){
8 System.out.println("array is NULL");
9 }
10 //做第i趟排序
11 for(int i = 0; i < array.length-1;i++){
12 for(int j = i+1; j < array.length;j++){
13 //选出最小的记录进行交换
14 if(array[i]>array[j]){
15 swap(array,i,j);
16 }
17 }
18 }
19 }
插入排序
(1)算法描述
插入排序也是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对已未排序
的序列的数据,在已经有序的序列中从后向前找并进行插入。但是在进行插入的过程中需
要不断的将已经排序好的数据进行移位操作。
(2)算法实现
a.从第一个数据开始,将该元素认为已经排序好的序列。
b.取出下一个元素,在已经排序好的元素序列中从后向前进行扫描。
c.如果该元素(排序好的元素)大于新的元素,则将该元素移动到下一个位置
d.重复步骤c,知道找到已排序好的元素小于或者等于新元素的位置
e.将新的元素插入到该位置
f.重复步骤b
1 /**
2 *插入排序
3 * @date: 2018/8/15 19:42
4 */
5 public static void insertSort(int[] array){
6 //临界条件判断
7 if(array==null||array.length==0){
8 System.out.println("array is null");
9 }
10 for(int i = 0; i < array.length;i++){
11 //从下一个元素进行遍历,若新元素小于已经排序好的序列的元素进行交换
12 for(int j = i ;(j>0)&&(array[j-1]>array[j]);j--){
13 swap(array,j-1,j);
14 }
15 }
16 }
Shell排序(希尔排序)
(1)算法描述
希尔排序是插入排序的一种,其中心思想是将数据进行分组,然后对每一组
数据进行排序,在每一组数据有序后,可以利用插入排序对所有分组进行最
后一次排序。这样可以减少数据交换的次数,加快排序速度。
(2)算法实现
a.选择一个增序序列t(1),t(2)……t(n),其中t(n)=1
b.按照增量序列个数k,对序列进行k此排序
c.每次排序,根据对应的增量,分为若干个长度为m的子序列,分别对子序列
进行插入排序。当增量为1时一个序列来进行处理,表长即为整个序列的长度。
1 /**
2 *Shell排序(希尔排序)
3 * @date: 2018/8/15 20:07
4 */
5 public static void shellSort(int[] array){
6 if(array==null||array.length==0){
7 System.out.println("array is null");
8 }
9 //分隔集合之间的长度(第一次假设为集合长度的一半)
10 int increment = 0;
11 //分隔集合之间的长度,每次为前一次的一半(最后一次为1)
12 for(increment = array.length/2;increment>0;increment = increment>>1){
13 for(int i = increment;i<array.length;i++){
14 for(int j = i - increment;j >= 0;j = j - increment){
15 if(array[i] < array[j]){
16 swap(array,i,j);
17 }
18 }
19 }
20 }
21 }
快速排序
(1)算法描述
快速排序是一种划分交换排序,采用分治的策略(分治法)。通过一趟排序
将待排序序列划分为两个独立的部分,其中一部分的记录的关键字均小于另
外一部分的关键字。 分法法的基本思想:将原问题分解为若干个规模更小但是结构和原问题相似
的子问题,递归地解决这些子问题,然后将这些子问题的解组合成原问题的解。
(2)算法实现
a.从数组序列中选择一个“基准元素”(此文中以每个序列第一个元素为准)
b.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准
值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,
该基准就处于数列的中间位置。这个称为分区操作
c.递归地把小于基准值元素的子数列和大于基准值元素的子数列排序。
1 public class Sort {
2 public static void main(String[] args) {
3 int [] arr = new int[]{4,2,1,6,3,6,0,-5,1,1};
4 quickSort(arr,0,arr.length-1);
5 //遍历打印排序后的数组
6 for(int i = 0; i < arr.length;i++){
7 System.out.print(arr[i]+" ");
8 }
9 }
10 /**
11 *快速排序
12 * @exception: array为待排序序列,low为要排序序列的下界,high为要排序序列的上界
13 * @date: 2018/8/16 9:41
14 */
15 public static void quickSort(int[] array,int low,int high){
16 if(array==null||array.length==0){
17 System.out.println("array is null");
18 }
19 //划分后的基准元素
20 int standard;
21 //区间长度小于1不需要再进行排序
22 if(low>=high){
23 return;
24 }
25 //对low……high进行划分
26 standard = partition(array,low,high);
27 //对左区间进行递归排序
28 quickSort(array,low,standard-1);
29 //对右区间进行递归排序
30 quickSort(array,standard+1,high);
31 }
32 /**
33 *对区间进行划分
34 * @date: 2018/8/16 9:49
35 */
36 private static int partition(int[] array, int low, int high) {
37 //进行临界判断
38 if(array==null||array.length==0){
39 return 0;
40 }
41 //基准元素,以区间第一个元素为准
42 int standardValue = array[low];
43 //区间长度小于1不需要进行划分
44 if(low>=high){
45 return low;
46 }
47 //区间两端交替向中间扫描,直至low=high为止
48 while(low<high){
49 //(standardValue相当于在位置low上)
50 while((low<high)&&(standardValue<=array[high])){
51 //从右向左扫描,查找第一个关键字小于基准元素standardValue值的记录
52 high--;
53 }
54 //表示找到小于基准元素standardValue值的记录
55 if(low<high){
56 //相当于交换low和high位置的值
57 array[low++] = array[high];
58 }
59 //(standardValue相当于在位置high上)
60 while((low<high)&&(array[low]<=standardValue)){
61 //从左向右扫描,查找第一个关键字大于standardValue值的记录
62 low++;
63 }
64 //表示找到大于基准元素standardValue值的记录
65 if(low<high){
66 //交换low和high的值
67 array[high--] = array[low];
68 }
69 }
70 //基准位置被最后定位
71 array[low] = standardValue;
72 return low;
73 }
74 }
归并排序
(1)算法描述
归并算法是在归并操作上的一种有效的排序算法,同样采用分治法。是将已经有序
的子序列进行合并,得到完全的有序序列,即先使得子序列有序,再使子序列段有
序,将两个有序序列合并为一个有序序列,称为“二路合并”。
(2)算法实现
a.将长度为n的序列划分为长度为n/2的两个子序列。
b.分别对这两个子序列采用归并排序。
c.将这两个已经有序的子序列进行合并。
1 public class Sort {
2 public static void main(String[] args) {
3 int [] arr = new int[]{4,2,1,6,3,6,0,-5,1,1};
4 quickSort(arr,0,arr.length-1);
5 mergeSort(arr);
6 //遍历打印排序后的数组
7 for(int i = 0; i < arr.length;i++){
8 System.out.print(arr[i]+" ");
9 }
10 }
11 /**
12 *归并排序
13 * array为待排序序列,left、right为序列的左右边界,temp为和原序列长度相等的临时序列
14 * @date: 2018/8/16 11:31
15 */
16 public static void mergeSort(int[] array){
17 //在排序前创建与原数组大小相等的临时数组,避免递归过程中频繁开辟空间
18 int[] temp = new int[array.length];
19 mergeSort(array,0,array.length-1,temp);
20 }
21 private static void mergeSort(int[] array,int left,int right,int[] temp){
22 if(left<right){
23 int mid = left + (right-left)/2;
24 //左半边序列进行归并排序,使得其有序
25 mergeSort(array,left,mid,temp);
26 //有半边序列进行归并排序,使得其有序
27 mergeSort(array,mid+1,right,temp);
28 //将两个子序列进行合并
29 merge(array,left,mid,right,temp);
30 }
31 }
32 private static void merge(int[] array,int left,int middle,int right,int[] temp){
33 if(array==null||array.length==0){
34 System.out.println("array is null");
35 }
36 //左序列指针指向
37 int leftPoint = left;
38 //有序列指针指向
39 int rightPoint = middle+1;
40 //临时数组的指针指向
41 int tempPoint = 0;
42 while (leftPoint<=middle&&rightPoint<=right){
43 if(array[leftPoint]<=array[rightPoint]){
44 temp[tempPoint++] = array[leftPoint++];
45 }else{
46 temp[tempPoint++] = array[rightPoint++];
47 }
48 }
49 //将左半序列中的元素添加至temp数组中
50 while (leftPoint<=middle){
51 temp[tempPoint++] = array[leftPoint++];
52 }
53 //将右半序列中的元素添加至temp数组中
54 while(rightPoint<=right){
55 temp[tempPoint++] = array[rightPoint++];
56 }
57 tempPoint = 0;
58 //将temp中元素拷贝至原数组中
59 while (left<=right){
60 array[left++] = temp[tempPoint++];
61 }
62 }
63 }
【排序算法】——冒泡排序、选择排序、插入排序、Shell排序等排序原理及Java实现的更多相关文章
- php基础排序算法 冒泡排序 选择排序 插入排序 归并排序 快速排序
<?php$arr=array(12,25,56,1,75,13,58,99,22);//冒泡排序function sortnum($arr){ $num=count($arr); ...
- C语言中的排序算法--冒泡排序,选择排序,希尔排序
冒泡排序(Bubble Sort,台湾译为:泡沫排序或气泡排序)是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没 ...
- 归并排序 & 计数排序 & 基数排序 & 冒泡排序 & 选择排序 ----> 内部排序性能比较
2.3 归并排序 接口定义: int merge(void* data, int esize, int lpos, int dpos, int rpos, int (*compare)(const v ...
- 数据结构和算法(Golang实现)(19)排序算法-冒泡排序
冒泡排序 冒泡排序是大多数人学的第一种排序算法,在面试中,也是问的最多的一种,有时候还要求手写排序代码,因为比较简单. 冒泡排序属于交换类的排序算法. 一.算法介绍 现在有一堆乱序的数,比如:5 9 ...
- Python排序算法——冒泡排序
有趣的事,Python永远不会缺席! 如需转发,请注明出处:小婷儿的python https://www.cnblogs.com/xxtalhr/p/10786904.html 一.冒泡排序(Bubb ...
- 排序算法--冒泡排序(Bubble Sort)_C#程序实现
排序算法--冒泡排序(Bubble Sort)_C#程序实现 排序(Sort)是计算机程序设计中的一种重要操作,也是日常生活中经常遇到的问题.例如,字典中的单词是以字母的顺序排列,否则,使用起来非常困 ...
- Python排序算法之选择排序定义与用法示例
Python排序算法之选择排序定义与用法示例 这篇文章主要介绍了Python排序算法之选择排序定义与用法,简单描述了选择排序的功能.原理,并结合实例形式分析了Python定义与使用选择排序的相关操作技 ...
- js 实现排序算法 -- 冒泡排序(Bubble Sort)
原文: 十大经典排序算法(动图演示) 冒泡排序(Bubble Sort) 冒泡排序是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来.走访数列的工作 ...
- Java 排序算法-冒泡排序及其优化
Java 排序算法-冒泡排序及其优化 什么是冒泡排序 基本写法 优化后写法 终极版本 源码及测试 什么是冒泡排序 这里引用一下百度百科上的定义: 冒泡排序(Bubble Sort),是一种计算机科学领 ...
- 使用 js 实现十大排序算法: 冒泡排序
使用 js 实现十大排序算法: 冒泡排序 冒泡排序 refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!
随机推荐
- SpringCloud 2020.0.4 系列之 Sleuth + Zipkin
1. 概述 老话说的好:安全不能带来财富,但盲目的冒险也是不可取的,大胆筹划,小心实施才是上策. 言归正传,微服务的特点就是服务多,服务间的互相调用也很复杂,就像一张关系网,因此为了更好的定位故障和优 ...
- List<String>转List<Integer>
List<Integer> intList = strList.stream().map(Integer::parseInt).collect(Collectors.toList()); ...
- 几个你不知道的dubbo注册中心细节
你会正确配置backup地址吗? 在配置dubbo注册中心时,一般会这样写 dubbo.registry.protocol=zookeeper dubbo.registry.address=127.0 ...
- 工程中实际问题解决两例——基于C#
工程中实际问题解决两例--基于C# 目录 工程中实际问题解决两例--基于C# 1. try catch的妙用 1.1 遇到问题的现象 1.2 原因分析 1.2.1 先从数据库入手 1.2.2 代码日志 ...
- 菜鸡的Java笔记 java基础类库 BaseClassLibrary
java基础类库 BaseClassLibrary StringBuffer 类的特点 StringBuffer,StringBuilder,String 类之间的关系 ...
- Java设计模式之(四)——原型模式
1.什么是原型模式 Specify the kinds of objects to create using a prototypical instance,and create new object ...
- vue-ref指令
$refs是数组
- uniapp中mqtt的基本使用
参考文档: [1] https://www.hivemq.com/blog/mqtt-client-library-mqtt-js/ [2] https://www.tabnine.com/code/ ...
- P6072 『MdOI R1』Path
考虑我们有这样操作. 我们只要维护两点在子树内和两点在子树外的异或和即可. 前者可以类似于线段树合并的trie树合并. 后者有两种做法: 一种是把dfn序翻倍:然后子树补变成了一个区间最大异或问题,可 ...
- LOJ 2353 & 洛谷 P4027 [NOI2007]货币兑换(CDQ 分治维护斜率优化)
题目传送门 纪念一下第一道(?)自己 yy 出来的 NOI 题. 考虑 dp,\(dp[i]\) 表示到第 \(i\) 天最多有多少钱. 那么有 \(dp[i]=\max\{\max\limits_{ ...