几种经典的数据排序及其Java实现

选择排序

思想

n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果:
①初始状态:无序区为R[1..n],有序区为空。
②第1趟排序
在无序区R[1..n]中选出关键字最小的记录R[k],将它与无序区的第1个记录R[1]交换,使R[1..1]和R[2..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。
……
③第i趟排序

第i趟排序开始时,当前有序区和无序区分别为R[1..i-1]和R(i..n)。该趟排序从当前无序区中选出关键字最小的记录 R[k],将它与无序区的第1个记录R交换,使R[1..i]和R分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。

排序实例


初始关键字 [49 38 65 97 76 13 27 49]
第一趟排序后 13 [38 65 97 76 49 27 49]
第二趟排序后 13 27 [65 97 76 49 38 49]
第三趟排序后 13 27 38 [97 76 49 65 49]
第四趟排序后 13 27 38 49 [76 97 65 49 ]
第五趟排序后 13 27 38 49 49 [97 65 76]
第六趟排序后 13 27 38 49 49 65 [97 76]
第七趟排序后 13 27 38 49 49 65 76 [97]
最后排序结果 13 27 38 49 49 65 76 97

Java实现代码如下:

 

package selectsort;public class Sort {public static void main(String[] args){int[] a = {8,77,66,99,2,7,4,6,100,34};int[] b ; b = selectsort(a);for(int i  = 0; i < b.length; i++){System.out.println(b[i]);}}public static int[] selectsort(int[] p){int temp = 0;int minindex = 0;int[] array = p.clone();for(int i = 0; i < array.length; i++){minindex = i;for(int j = i+1; j < array.length; j++){if(array[minindex] > array[j] )minindex = j;}temp = array[i];array[i] = array[minindex];array[minindex] = temp;}return array;}
}


结果验证正确。

 

冒泡法

原理


冒泡排序算法的运作如下:
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
算法分析


算法稳定性


冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。

Java实现代码:

 

package bubblesort;public class Bubblesort {public static void main(String[] args){int[] a = {8,77,66,99,2,7,4,6,100,34};int[] b;b = bubble(a);for(int i =0; i <b.length; i++ ){System.out.println(b[i]);}}public static int[] bubble(int[] a){int[] array = a.clone();for(int i  = 0; i < array.length - 1; i++){for(int j = 0; j < array.length - 1 - i; j++){if(array[j] > array[j+1])sway(array,j,j+1);}}return array;}public static void sway(int[] b, int m, int n){int temp = b[m];b[m] = b[n];b[n] = temp;}}

插入排序

插入排序(Insertion Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

算法描述一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下:从第一个元素开始,该元素可以认为已经被排序取出下一个元素,在已经排序的元素序列中从后向前扫描如果该元素(已排序)大于新元素,将该元素移到下一位置重复步骤3,直到找到已排序的元素小于或者等于新元素的位置将新元素插入到该位置后重复步骤2~5如果比较操作的代价比交换操作大的话,可以采用二分查找法来减少比较操作的数目。该算法可以认为是插入排序的一个变种,称为二分查找排序。

Java示例代码如下:

 

package insertsort;public class Insert {public static void main(String[] args){int[] a = {500,77,66,99,2,7,4,6,100,34};int[] b;b = insert(a);for(int i =0; i <b.length; i++ ){System.out.println(b[i]);}}public static int[] insert(int[] c){int[] array = c.clone();for(int i  = 1; i < array.length; i++){if(array[i] < array[i - 1]){int temp = array[i];int j  = i;while((j>0)&&(array[j - 1] > temp)){array[j] = array[j - 1];j--;}array[j] = temp; }}return array;}
}


希尔排序

 

希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能。这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)。
假设有一个很小的数据在一个已按升序排好序的数组的末端。如果用复杂度为O(n2)的排序(冒泡排序或插入排序),可能会进行n次的比较和交换才能将该数据移至正确位置。而希尔排序会用较大的步长移动数据,所以小数据只需进行少数比较和交换即可到正确位置。
一个更好理解的希尔排序实现:将数组列在一个表中并对列排序(用插入排序)。重复这过程,不过每次用更长的列来进行。最后整个表就只有一列了。将数组转换至表是为了更好地理解这算法,算法本身仅仅对原数组进行排序(通过增加索引的步长,例如是用i += step_size而不是i++)。
例如,假设有这样一组数[ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ],如果我们以步长为5开始进行排序,我们可以通过将这列表放在有5列的表中来更好地描述算法,这样他们就应该看起来是这样:
13 14 94 33 82
25 59 94 65 23
45 27 73 25 39
10
然后我们对每列进行排序:
10 14 73 25 23
13 27 94 33 39
25 59 94 65 82
45
将上述四行数字,依序接在一起时我们得到:[ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ].这时10已经移至正确位置了,然后再以3为步长进行排序:
10 14 73
25 23 13
27 94 33
39 25 59
94 65 82
45
排序之后变为:
10 14 13
25 23 33
27 25 59
39 65 73
45 94 82
94
最后以1步长进行排序(此时就是简单的插入排序了)。

 

 



package shellsort;public class shellsort {public static void main(String[] args){int[] a = {500,77,66,99,2,7,4,6,100,34};int[] b;b = shell(a);for(int i =0; i <b.length; i++ ){System.out.println(b[i]);}}public static int[] shell(int[] a){int[] array = a.clone();int len = array.length;int i = 0;int j = 0;int k = -1;int temp = -1;int gap = len;do{gap = gap / 3 + 1; for(i=gap; i<len; i+=gap){k = i;temp = array[k];for(j=i-gap; (j>=0) && (array[j]>temp); j-=gap){array[j+gap] = array[j];k = j;}array[k] = temp;}}while( gap > 1 );return array;}
}

快速排序

思想:从待排序记录序列中选取一个记录(通常选取第一个记录)为枢轴其关键字设为k1,然后将其余关键字小于k1的记录移到前面去,而将关键字大于k1的记录移到后面,结果将待排序序列分成了两个子表最后将关键字为k1的记录查到其分界线的位置处.
算法步骤:假设待划分序列为r[left],r[left+1],.......r[right],具体实现上述划分过程时,可以设两个指针i和j,他们的初值分别为left,right.首先将基准记录r[left]移至变量x中,是r[left],即r[i]相当于空单元,然后反复进行如下两个扫描过程,直到i和j相遇
(1)j从右向左扫描,直到r[j].key<x.key时,将r[j]移至控单元r[i],此时r[j]相当于控单元。
(2)i从左向后扫描,直到r[i].key>x.key时,将r[i]移至空单元r[j],此时r[i]相当于空单元。
当i和j相遇时,r[i](或r[j])相当与空单元,且r[i]左边所有记录的关键字均不大于基准记录的关键字,而r[i]右边所有记录的关键字均不小于基准记录的关键字,最后将基准记录移至r[i]中,就完成了一次划分过程。最后对子表进行递归调用排序函数进行排序。
Java示例代码如下:
package quicksort;public class Quick {public static void main(String[] args){int[] a = {500,77,66,99,2,7,4,6,100,34,1000,888,777,666,555,333,222,111,87,45,69,12,45,};QuickSort(a,a.length);for(int i =0; i <a.length; i++ ){System.out.println(a[i]);}}public static void swap(int[] array, int i, int j){int temp = array[i];array[i] = array[j];array[j] = temp;}public static int partition(int[] array, int low, int high){int pv = array[low];while( low < high ){while( (low < high) && (array[high] >= pv) ){high--;}swap(array, low, high);while( (low < high) && (array[low] <= pv) ){low++;}swap(array, low, high);}return low;}public static void QSort(int[] array, int low, int high){if( low < high ){int pivot = partition(array, low, high);QSort(array, low, pivot-1);QSort(array, pivot+1, high);}}public static void QuickSort(int[] array, int len) // O(n*logn){QSort(array, 0, len-1);}}

归并排序
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。值得注意的是归并排序是一种稳定的排序方法。
将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
归并操作
归并操作(merge),也叫归并算法,指的是将两个顺序序列合并成一个顺序序列的方法。
如 设有数列{6,202,100,301,38,8,1}
初始状态:6,202,100,301,38,8,1
第一次归并后:{6,202},{100,301},{8,38},{1},比较次数:3;
第二次归并后:{6,100,202,301},{1,8,38},比较次数:4;
第三次归并后:{1,6,8,38,100,202,301},比较次数:4;
总的比较次数为:3+4+4=11,;
逆序数为14;
算法描述
归并操作的工作原理如下:
第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置
第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
重复步骤3直到某一指针超出序列尾
将另一序列剩下的所有元素直接复制到合并序列尾
Java示例代码如下:
package MergeSortClass;public class MergeSortClass {private int[] SortOut;public void printSortedOutput() {for (int i = 0; i < this.SortOut.length; i++) {System.out.print(this.SortOut[i] + " ");}}public static void main(String[] args) {int[] in = { 2, 5, 3, 8, 6, 7, 1, 4, 0, 9 };MergeSortClass msTest = new MergeSortClass(in);msTest.printSortedOutput();}public MergeSortClass(int[] in){this.SortOut=this.MergeSort(in);}private int[] MergeSort(int[] i_list){if (i_list.length == 1) {return i_list;} else {int[] listL = new int[i_list.length / 2];int[] listR = new int[i_list.length - i_list.length / 2];int Center = i_list.length / 2;for (int i = 0; i < Center; i++) {listL[i] = i_list[i];}for (int i = Center, j = 0; i < i_list.length; i++, j++) {listR[j] = i_list[i];}int[] SortedListL=MergeSort(listL);int[] SortedListR=MergeSort(listR);int[] o_list = MergeTwoList(SortedListL, SortedListR);return o_list;}}private int[] MergeTwoList(int[] listL, int[] listR) {int i = 0, j = 0;int[] o_list = new int[listL.length + listR.length];int foot = 0;while (i < listL.length && j < listR.length) {if (listL[i] <= listR[j]) {o_list[foot] = listL[i];i++;} else {o_list[foot] = listR[j];j++;}foot++;}if (i == listL.length) {while (j < listR.length) {o_list[foot++] = listR[j++];}} else { // j==listR.lengthwhile (i < listL.length) {o_list[foot++] = listL[i++];}}return o_list;}
}






转载于:https://www.cnblogs.com/riasky/p/3455594.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/263092.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

远见卓识,领导力在于把握企业潮流

凡是有人群的地方就有领导力&#xff0c;凡是有思想、有文化的地方就有领导力。经济学里&#xff0c;是在市场的意义上研究领导力&#xff1a;谁在引领价格变动的方式&#xff0c;谁在引领技术变化的潮流&#xff0c;谁在引导产品的发展趋势&#xff0c;这些都是领导力的概念。…

关于SqlBulkCopy SQL批量导入需要注意,列名是区分大小写的

最近在做数据从Excel批量导入MSSQL时&#xff0c;传统的是使用Insert Into Table方法&#xff0c;不过这个方便比较慢 通过使用 SqlBulkCopy 可以批量导入到数据库。 默认批量导入数据库&#xff0c;需要DataTable的构架和MSSQL的表结构一样。但是使用ColumnMappings可以对列明…

VMware开启NAT模式/仅主机模式后主机ping不通虚拟机的问题

VMware开启NAT模式/仅主机模式后主机ping不通虚拟机的问题问题&#xff1a;VMware设置网络模式为NAT模式后&#xff0c;我们使用主机ping虚拟机无法联通&#xff0c;用虚拟机ping主机可以联通。 原因&#xff1a;这是由于虚拟机的IP网段与主机的VMnet8网段不一致所造成的。 解…

linux下 mysql 忘记root用户密码解决办法

一、以系统的root用户&#xff08;什么&#xff0c;你的系统的root用户密码也忘了。那只好看我另外一篇linux下忘记root用户的解决办法了先解决这个问题&#xff09;登陆系统&#xff0c;进入终端 [rootlocalhost /]# 二、杀掉mysql进程 方法1、[rootlocalhost /]#killall m…

OO设计原则总结

什么是设计原则&#xff1f; 设计原则是基本的工具&#xff0c;应用这些规则可以使你的代码更加灵活、更容易维护&#xff0c;更容易扩展。 基本原则封装变化Encapsulate what varies. 面向接口编程而非实现 Code to an interface rather than to an implementation.优先使用组…

kubectl get node运行时出现:Unable to connect to the server: x509: certificate signed by unknown authority

kubectl get nodes运行时出现&#xff1a;Unable to connect to the server: x509: certificate signed by unknown authority原因&#xff1a;我们在运行kubeadm reset时&#xff0c;没有删除原先的$HOME/.kube文件导致新建的kubelet报错。实际上在kubeadm reset执行后&#x…

设置在VS2005的IDE中迅速打开xaml文件

设置在VS2005的IDE中迅速打开xaml文件 本人使用普通台式计算机做WPF开发&#xff0c;每次打开xaml的时候&#xff0c;都需要等半天&#xff0c;那叫一个慢呀&#xff0c;实在受不了。即使是一个新建的xaml文件&#xff0c;打开都慢。怎样解决VS2005的IDE中打开xaml文件慢的问题…

Git分支(远程)

1、远程分支的表示形式&#xff1a;远程仓库名称/分支名&#xff0c;如&#xff1a;origin/master&#xff1b;2、一次Git克隆会建立你自己的本地分支&#xff1a;master和远程分支&#xff1a;origin/master&#xff0c;它们都指向origin/master分支的最后一次提交&#xff1b…

kubeadm join时出现错误:[ERROR Port-10250]: Port 10250 is in use [ERROR FileAvailable--etc-kubernetes-pki

kubeadm join时出现错误&#xff1a;[ERROR Port-10250]: Port 10250 is in use&#xff1b;[ERROR FileAvailable--etc-kubernetes-pki-ca.crt]: /etc/kubernetes/pki/ca.crt already exists初次使用kubeadm构建k8s集群&#xff0c;所以对子节点加入管理节点的过程认识不足&am…

cs文件中控制页面table的大小、title名称(.aspx)

1. title 控制HTML:<title id"mytitle" runat"server"></title> CS: protected System.Web.UI.HtmlControls.HtmlGenericControl mytitle;mytitle.InnerText "Hello World"; 2. 页面table 控制HTML:<TABLE idTabl…

TCP/IP详解学习笔记(2)-数据链路层

TCP/IP详解学习笔记(2)-数据链路层数据链路层有三个目的&#xff1a; 为IP模块发送和 接收IP数据报。 为ARP模块发送ARP请求和接收ARP应答。 为RARP发送RARP请 求和接收RARP应答ip大家都听说过。至于ARP和RARP&#xff0c;ARP叫做地址解析协议…

vi 按了ctrl+s怎么办

【转载】 手香的不得了 http://blog.sina.com.cn/lx987654321123456789 今天白痴了一把&#xff0c;用vi的时候&#xff0c;习惯性的用了ctrl-s&#xff0c;一下子僵掉了网上一查&#xff0c; 原来&#xff1a; CTRLS表示停止向终端停止输出; CTRLQ恢复向终端输出流. 严重bs自己…

POJ 1966 Cable TV Network (最大流最小割)

$ POJ~1966~Cable~TV~Network $ $ solution: $ 第一眼可能让人很难下手&#xff0c;但本就是冲着网络流来的&#xff0c;所以我们直接一点。这道题我们要让这个联通图断开&#xff0c;那么势必会有两个点变得不连通&#xff0c;这道题的数据范围很小&#xff0c;所以我们试着暴…

harbor安装时出现ERROR: An HTTP request took too long to complete. Retry with --verbose to obtain debug in

harbor安装时出现ERROR: An HTTP request took too long to complete. Retry with --verbose to obtain debug information.If you encounter this issue regularly because of slow network conditions, consider setting COMPOSE_HTTP_TIMEOUT to a higher value current val…

几大开源项目

7-Zip 4.32&#xff1a;文件压缩工具&#xff0c;可与Windows资源管理器集成 A Note 4.2.1&#xff1a;可在Windows桌面放置便笺&#xff0c;并可提供闹钟提醒功能 Abakt 0.9&#xff1a;能够以压缩方式对文档进行备份 Abiword 2.27&#xff1a;Windows写字板的替代程序&…

如何恢复Linux下被误删除的文件以及如何防止文件被删除

【卸载被误删除文件所在的分区&#xff0c;或以只读方式mount】当你发现你误删除了文件后&#xff0c;要做的第一件事情是马上卸载被误删除文件所在分区&#xff0c;或者以只读的方式来挂在该防区。如果误删除的是根分区&#xff0c;最好直接断电&#xff0c;进入单用户模式&am…

配置msdtc

配置msdtc需要分别配置数据库服务器和开发机&#xff0c;因为只有两个机器都配置正确了&#xff0c;分布式事务才不会报乌七八糟的错误。如果数据库服务器和开发机是同一台机器&#xff0c;那就不用看本文了&#xff0c;因为不存在分布式事务的问题。 数据库服务器和开发机中配…

GooglePR说明

内容摘要&#xff1a;无论是对普通网络冲浪者还是网站管理员来说&#xff0c;Google都是目前世界范围内最受欢迎的搜索引擎。它每天处理的搜索请求高达1.5亿次&#xff0c;几乎占全球所有搜索量的1/3。网络冲浪者对Google情有独钟&#xff0c;是由于Google所提供的快速搜索速度…

什么是套接字?Socket基本介绍

什么是套接字&#xff1f;Socket基本介绍一、什么是套接字&#xff1f;二、套接字特性三、套接字缓冲区一、什么是套接字&#xff1f; 套接字是一种通信机制&#xff08;通信的两方的一种约定&#xff09;&#xff0c;socket屏蔽了各个协议的通信细节&#xff0c;提供了tcp/ip…

[ZJOI2007] 时态同步

题面 显然的一个建模是&#xff0c;每个叶子对应一个权值&#xff0c;代表比最晚的叶子早了多久&#xff0c;然后我们要做的就是给每条边赋上值&#xff0c;使得每个叶子到根的路径上的所有边权值和等于叶子的权值。 我们贪心的想一想&#xff0c;必然是离根越近的边赋值多的情…