java排序算法冒泡
实例说明
用冒泡排序方法对数组进行排序。
实例解析
交换排序的基本思想是两两比较待排序记录的关键字,发现两个记录的次序相反时即进行交换,直到没有反序的记录为止。
应用交换排序基本思想的主要排序方法有冒泡排序和快速排序。
冒泡排序
将被排序的记录数组 R[1..n] 垂直排列,每个记录 R[i] 看做是重量为 R[i].key 的气泡。根据轻气泡不能在重气泡之下的原则,从下往上扫描数组 R 。凡扫描到违反本原则的轻气泡,就使其向上“漂浮”。如此反复进行,直到最后任何两个气泡都是轻者在上,重者在下为止。
(1) 初始, R[1..n] 为无序区。
(2) 第一趟扫描,从无序区底部向上依次比较相邻的两个气泡的重量,若发现轻者在下、重者在上,则交换二者的位置。即依次比较 (R[n],R[n-1]) 、 (R[n-1],R[n-2]) 、 … 、 (R[2],R[1]); 对于每对气泡 (R[j+1],R[j]), 若 R[j+1].key<R[j].key, 则交换 R[j+1] 和 R[j] 的内容。
第一趟扫描完毕时,“最轻”的气泡就飘浮到该区间的顶部,即关键字最小的记录被放在最高位置 R[1] 上。
(3) 第二趟扫描,扫描 R[2..n]。扫描完毕时,“次轻”的气泡飘浮到 R[2] 的位置上 …… 最后,经过 n-1 趟扫描可得到有序区 R[1..n]。
注意:第 i 趟扫描时, R[1..i-1] 和 R[i..n] 分别为当前的有序区和无序区。扫描仍是从无序区底部向上直至该区顶部。扫描完毕时,该区中最轻气泡漂浮到顶部位置 R[i] 上,结果是 R[1..i] 变为新的有序区。
冒泡排序算法
因为每一趟排序都使有序区增加了一个气泡,在经过 n-1 趟排序之后,有序区中就有 n-1 个气泡,而无序区中气泡的重量总是大于等于有序区中气泡的重量,所以整个冒泡排序过程至多需要进行 n-1 趟排序。
若在某一趟排序中未发现气泡位置的交换,则说明待排序的无序区中所有气泡均满足轻者在上,重者在下的原则,因此,冒泡排序过程可在此趟排序后终止。为此,在下面给出的算法中,引入一个布尔量 exchange, 在每趟排序开始前,先将其置为 FALSE 。若排序过程中发生了交换,则将其置为 TRUE 。各趟排序结束时检查 exchange, 若未曾发生过交换则终止算法,不再进行下趟排序。
具体算法如下:
void BubbleSort(SeqList R){
//R(1..n) 是待排序的文件,采用自下向上扫描,对 R 做冒泡排序
int i,j;
Boolean exchange; // 交换标志
for(i=1;i<n;i++){ // 最多做 n-1 趟排序
exchange=FALSE; // 本趟排序开始前,交换标志应为假
for(j=n-1;j>=i;j--) // 对当前无序区 R[i..n] 自下向上扫描
if(R[j+1].key<R[j].key){ // 交换记录
R[0]=R[j+1]; //R[0] 不是哨兵,仅做暂存单元
R[j+1]=R[j];
R[j]=R[0];
exchange=TRUE; // 发生了交换,故将交换标志置为真
}
if(!exchange) // 本趟排序未发生交换,提前终止算法
return;
} //endfor( 外循环 )
}//BubbleSort
publicclassBubbleSort{
publicstaticvoidmain(String[]args){
//TODOAuto-generatedmethodstub
List<Integer>lstInteger=newArrayList<Integer>();
lstInteger.add(1);
lstInteger.add(1);
lstInteger.add(3);
lstInteger.add(2);
lstInteger.add(1);
for(inti=0;i<lstInteger.size();i++){
System.out.println(lstInteger.get(i));
}
System.out.println("排序之后-----------------");
lstInteger=sortList(lstInteger);
for(inti=0;i<lstInteger.size();i++){
System.out.println(lstInteger.get(i));
}
}
publicstaticList<Integer>sortList(List<Integer>lstInteger){
inti,j,m;
booleanblChange;
intn=lstInteger.size();
for(i=0;i<n;i++){
blChange=false;
for(j=n-1;j>i;j--){
if(lstInteger.get(j)<lstInteger.get(j-1)){
m=lstInteger.get(j-1);
lstInteger.set(j-1,lstInteger.get(j));
lstInteger.set(j,m);
blChange=true;
}
}
if(!blChange){
returnlstInteger;
}
}
returnlstInteger;
}
}
归纳注释
算法的最好时间复杂度:若文件的初始状态是正序的,一趟扫描即可完成排序。所需的关键字比较次数C和记录移动次数M均达到最小值,即C(min)=n-1,M(min)=0。冒泡排序最好的时间复杂度为O(n)。
算法的最坏时间复杂度:若初始文件是反序的,需要进行n-1趟排序。每趟排序要进行n-1次关键字的比较(1<=i<=n-1),且每次比较都必须移动记录3次。在这种情况下,比较和移动次数均达到最大值,即C(max)=n(n-1)/2=O(n^2),M(max)=3n(n-1)/2=O(n^2)。冒泡排序的最坏时间复杂度为O(n^2)。
算法的平均时间复杂度为O(n^2)。虽然冒泡排序不一定要进行n-1趟,但由于它的记录移动次数较多,故平均时间性能比直接插入排序要差得多。
算法稳定性:冒泡排序是就地排序,且它是稳定的。
算法改进:上述的冒泡排序还可做如下的改进,①记住最后一次交换发生位置lastExchange的冒泡排序(该位置之前的相邻记录均已有序)。下一趟排序开始时,R[1..lastExchange-1]是有序区,R[lastExchange..n]是无序区。这样,一趟排序可能使当前有序区扩充多个记录,从而减少排序的趟数。②改变扫描方向的冒泡排序。冒泡排序具有不对称性。能一趟扫描完成排序的情况,只有最轻的气泡位于R[n]的位置,其余的气泡均已排好序,那么也只需一趟扫描就可以完成排序。如对初始关键字序列12、18、42、44、45、67、94、10就仅需一趟扫描。需要n-1趟扫描完成排序情况,当只有最重的气泡位于R[1]的位置,其余的气泡均已排好序时,则仍需做n-1趟扫描才能完成排序。比如对初始关键字序列:94、10、12、18、42、44、45、67就需7趟扫描。造成不对称性的原因是每趟扫描仅能使最重气泡“下沉”一个位置,因此使位于顶端的最重气泡下沉到底部时,需做n-1趟扫描。在排序过程中交替改变扫描方向,可改进不对称性
Ⅱ java冒泡排序详细讲解
就是 一组数字组成的数组,两两比较,大的数往后推,小的数向前
从头开始扫描待排序的元素,在扫描过程中依次对相邻元素进行比较,将关键字值大的元素后移。每经过一趟排序后,关键字值最大的元素将移到末尾,此时记下该元素的位置,下一趟排序只需要比较到此位置为止,直到所有元素都已有序排列。
Ⅲ java实现几种常见排序算法
下面给你介绍四种常用排序算法:
1、冒泡排序
特点:效率低,实现简单
思想(从小到大排):每一趟将待排序序列中最大元素移到最后,剩下的为新的待排序序列,重复上述步骤直到排完所有元素。这只是冒泡排序的一种,当然也可以从后往前排。
Ⅳ 用java冒泡排序和递归算法
冒泡排序
(1)基本思想:在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
(2)用java实现
ublicclassbubbleSort{
publicbubbleSort(){
inta[]={1,54,6,3,78,34,12,45};
inttemp=0;
for(inti=0;i<a.length;i++){
for(intj=i+1;j<a.length;j++){
if(a[i]>a[j]){
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
for(inti=0;i<a.length;i++)
System.out.println(a[i]);
}
}
递归
递归算法,就是程序的自身调用。表现在一段程序中往往会遇到调用自身的那样一种coding策略,可以利用大道至简的思想,把一个大的复杂的问题层层转换为一个小的和原问题相似的问题来求解的这样一种策略。能看到我们会用很少的语句解决了非常大的问题,所以递归策略的最主要体现就是小的代码量解决了非常复杂的问题。
java代码:
packagecom.cjq.filedown;
publicclassFab{
publicstaticvoidmain(Stringargs[]){
System.out.println(fab(5));
}
privatestaticintfab(intindex){
if(index==1||index==2){
return1;
}else{
returnfab(index-1)+fab(index-2);
}
}
}
Ⅳ Java通过几种经典的算法来实现数组排序
JAVA中在运用数组进行排序功能时,一般有四种方法:快速排序法、冒泡法、选择排序法、插入排序法。
快速排序法主要是运用了Arrays中的一个方法Arrays.sort()实现。
冒泡法是运用遍历数组进行比较,通过不断的比较将最小值或者最大值一个一个的遍历出来。
选择排序法是将数组的第一个数据作为最大或者最小的值,然后通过比较循环,输出有序的数组。
插入排序是选择一个数组中的数据,通过不断的插入比较最后进行排序。下面我就将他们的实现方法一一详解供大家参考。
<1>利用Arrays带有的排序方法快速排序
public class Test2{ public static void main(String[] args){ int[] a={5,4,2,4,9,1}; Arrays.sort(a); //进行排序 for(int i: a){ System.out.print(i); } } }
<2>冒泡排序算法
public static int[] bubbleSort(int[] args){//冒泡排序算法 for(int i=0;i<args.length-1;i++){ for(int j=i+1;j<args.length;j++){ if (args[i]>args[j]){ int temp=args[i]; args[i]=args[j]; args[j]=temp; } } } return args; }
<3>选择排序算法
public static int[] selectSort(int[] args){//选择排序算法 for (int i=0;i<args.length-1 ;i++ ){ int min=i; for (int j=i+1;j<args.length ;j++ ){ if (args[min]>args[j]){ min=j; } } if (min!=i){ int temp=args[i]; args[i]=args[min]; args[min]=temp; } } return args; }
<4>插入排序算法
public static int[] insertSort(int[] args){//插入排序算法 for(int i=1;i<args.length;i++){ for(int j=i;j>0;j--){ if (args[j]<args[j-1]){ int temp=args[j-1]; args[j-1]=args[j]; args[j]=temp; }else break; } } return args; }
Ⅵ 数据结构 java开发中常用的排序算法有哪些
排序算法有很多,所以在特定情景中使用哪一种算法很重要。为了选择合适的算法,可以按照建议的顺序考虑以下标准:
(1)执行时间
(2)存储空间
(3)编程工作
对于数据量较小的情形,(1)(2)差别不大,主要考虑(3);而对于数据量大的,(1)为首要。
主要排序法有:
一、冒泡(Bubble)排序——相邻交换
二、选择排序——每次最小/大排在相应的位置
三、插入排序——将下一个插入已排好的序列中
四、壳(Shell)排序——缩小增量
五、归并排序
六、快速排序
七、堆排序
八、拓扑排序
一、冒泡(Bubble)排序
----------------------------------Code 从小到大排序n个数------------------------------------
void BubbleSortArray()
{
for(int i=1;i<n;i++)
{
for(int j=0;i<n-i;j++)
{
if(a[j]>a[j+1])//比较交换相邻元素
{
int temp;
temp=a[j]; a[j]=a[j+1]; a[j+1]=temp;
}
}
}
}
-------------------------------------------------Code------------------------------------------------
效率 O(n²),适用于排序小列表。
二、选择排序
----------------------------------Code 从小到大排序n个数--------------------------------
void SelectSortArray()
{
int min_index;
for(int i=0;i<n-1;i++)
{
min_index=i;
for(int j=i+1;j<n;j++)//每次扫描选择最小项
if(arr[j]<arr[min_index]) min_index=j;
if(min_index!=i)//找到最小项交换,即将这一项移到列表中的正确位置
{
int temp;
temp=arr[i]; arr[i]=arr[min_index]; arr[min_index]=temp;
}
}
}
-------------------------------------------------Code-----------------------------------------
效率O(n²),适用于排序小的列表。
三、插入排序
--------------------------------------------Code 从小到大排序n个数-------------------------------------
void InsertSortArray()
{
for(int i=1;i<n;i++)//循环从第二个数组元素开始,因为arr[0]作为最初已排序部分
{
int temp=arr[i];//temp标记为未排序第一个元素
int j=i-1;
while (j>=0 && arr[j]>temp)/*将temp与已排序元素从小到大比较,寻找temp应插入的位置*/
{
arr[j+1]=arr[j];
j--;
}
arr[j+1]=temp;
}
}
------------------------------Code--------------------------------------------------------------
最佳效率O(n);最糟效率O(n²)与冒泡、选择相同,适用于排序小列表
若列表基本有序,则插入排序比冒泡、选择更有效率。
四、壳(Shell)排序——缩小增量排序
-------------------------------------Code 从小到大排序n个数-------------------------------------
void ShellSortArray()
{
for(int incr=3;incr<0;incr--)//增量递减,以增量3,2,1为例
{
for(int L=0;L<(n-1)/incr;L++)//重复分成的每个子列表
{
for(int i=L+incr;i<n;i+=incr)//对每个子列表应用插入排序
{
int temp=arr[i];
int j=i-incr;
while(j>=0&&arr[j]>temp)
{
arr[j+incr]=arr[j];
j-=incr;
}
arr[j+incr]=temp;
}
}
}
}
--------------------------------------Code-------------------------------------------
适用于排序小列表。
效率估计O(nlog2^n)~O(n^1.5),取决于增量值的最初大小。建议使用质数作为增量值,因为如果增量值是2的幂,则在下一个通道中会再次比较相同的元素。
壳(Shell)排序改进了插入排序,减少了比较的次数。是不稳定的排序,因为排序过程中元素可能会前后跳跃。
五、归并排序
----------------------------------------------Code 从小到大排序---------------------------------------
void MergeSort(int low,int high)
{
if(low>=high) return;//每个子列表中剩下一个元素时停止
else int mid=(low+high)/2;/*将列表划分成相等的两个子列表,若有奇数个元素,则在左边子列表大于右侧子列表*/
MergeSort(low,mid);//子列表进一步划分
MergeSort(mid+1,high);
int [] B=new int [high-low+1];//新建一个数组,用于存放归并的元素
for(int i=low,j=mid+1,k=low;i<=mid && j<=high;k++)/*两个子列表进行排序归并,直到两个子列表中的一个结束*/
{
if (arr[i]<=arr[j];)
{
B[k]=arr[i];
I++;
}
else
{ B[k]=arr[j]; j++; }
}
for( ;j<=high;j++,k++)//如果第二个子列表中仍然有元素,则追加到新列表
B[k]=arr[j];
for( ;i<=mid;i++,k++)//如果在第一个子列表中仍然有元素,则追加到新列表中
B[k]=arr[i];
for(int z=0;z<high-low+1;z++)//将排序的数组B的 所有元素复制到原始数组arr中
arr[z]=B[z];
}
-----------------------------------------------------Code---------------------------------------------------
效率O(nlogn),归并的最佳、平均和最糟用例效率之间没有差异。
适用于排序大列表,基于分治法。
六、快速排序
------------------------------------Code--------------------------------------------
/*快速排序的算法思想:选定一个枢纽元素,对待排序序列进行分割,分割之后的序列一个部分小于枢纽元素,一个部分大于枢纽元素,再对这两个分割好的子序列进行上述的过程。*/ void swap(int a,int b){int t;t =a ;a =b ;b =t ;}
int Partition(int [] arr,int low,int high)
{
int pivot=arr[low];//采用子序列的第一个元素作为枢纽元素
while (low < high)
{
//从后往前栽后半部分中寻找第一个小于枢纽元素的元素
while (low < high && arr[high] >= pivot)
{
--high;
}
//将这个比枢纽元素小的元素交换到前半部分
swap(arr[low], arr[high]);
//从前往后在前半部分中寻找第一个大于枢纽元素的元素
while (low <high &&arr [low ]<=pivot )
{
++low ;
}
swap (arr [low ],arr [high ]);//将这个枢纽元素大的元素交换到后半部分
}
return low ;//返回枢纽元素所在的位置
}
void QuickSort(int [] a,int low,int high)
{
if (low <high )
{
int n=Partition (a ,low ,high );
QuickSort (a ,low ,n );
QuickSort (a ,n +1,high );
}
}
----------------------------------------Code-------------------------------------
平均效率O(nlogn),适用于排序大列表。
此算法的总时间取决于枢纽值的位置;选择第一个元素作为枢纽,可能导致O(n²)的最糟用例效率。若数基本有序,效率反而最差。选项中间值作为枢纽,效率是O(nlogn)。
基于分治法。
七、堆排序
最大堆:后者任一非终端节点的关键字均大于或等于它的左、右孩子的关键字,此时位于堆顶的节点的关键字是整个序列中最大的。
思想:
(1)令i=l,并令temp= kl ;
(2)计算i的左孩子j=2i+1;
(3)若j<=n-1,则转(4),否则转(6);
(4)比较kj和kj+1,若kj+1>kj,则令j=j+1,否则j不变;
(5)比较temp和kj,若kj>temp,则令ki等于kj,并令i=j,j=2i+1,并转(3),否则转(6)
(6)令ki等于temp,结束。
-----------------------------------------Code---------------------------
void HeapSort(SeqIAst R)
{ //对R[1..n]进行堆排序,不妨用R[0]做暂存单元 int I; BuildHeap(R); //将R[1-n]建成初始堆for(i=n;i>1;i--) //对当前无序区R[1..i]进行堆排序,共做n-1趟。{ R[0]=R[1]; R[1]=R[i]; R[i]=R[0]; //将堆顶和堆中最后一个记录交换 Heapify(R,1,i-1); //将R[1..i-1]重新调整为堆,仅有R[1]可能违反堆性质 } } ---------------------------------------Code--------------------------------------
堆排序的时间,主要由建立初始堆和反复重建堆这两部分的时间开销构成,它们均是通过调用Heapify实现的。
堆排序的最坏时间复杂度为O(nlgn)。堆排序的平均性能较接近于最坏性能。 由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。 堆排序是就地排序,辅助空间为O(1), 它是不稳定的排序方法。
堆排序与直接插入排序的区别:
直接选择排序中,为了从R[1..n]中选出关键字最小的记录,必须进行n-1次比较,然后在R[2..n]中选出关键字最小的记录,又需要做n-2次比较。事实上,后面的n-2次比较中,有许多比较可能在前面的n-1次比较中已经做过,但由于前一趟排序时未保留这些比较结果,所以后一趟排序时又重复执行了这些比较操作。
堆排序可通过树形结构保存部分比较结果,可减少比较次数。
八、拓扑排序
例 :学生选修课排课先后顺序
拓扑排序:把有向图中各顶点按照它们相互之间的优先关系排列成一个线性序列的过程。
方法:
在有向图中选一个没有前驱的顶点且输出
从图中删除该顶点和所有以它为尾的弧
重复上述两步,直至全部顶点均已输出(拓扑排序成功),或者当图中不存在无前驱的顶点(图中有回路)为止。
---------------------------------------Code--------------------------------------
void TopologicalSort()/*输出拓扑排序函数。若G无回路,则输出G的顶点的一个拓扑序列并返回OK,否则返回ERROR*/
{
int indegree[M];
int i,k,j;
char n;
int count=0;
Stack thestack;
FindInDegree(G,indegree);//对各顶点求入度indegree[0....num]
InitStack(thestack);//初始化栈
for(i=0;i<G.num;i++)
Console.WriteLine("结点"+G.vertices[i].data+"的入度为"+indegree[i]);
for(i=0;i<G.num;i++)
{
if(indegree[i]==0)
Push(thestack.vertices[i]);
}
Console.Write("拓扑排序输出顺序为:");
while(thestack.Peek()!=null)
{
Pop(thestack.Peek());
j=locatevex(G,n);
if (j==-2)
{
Console.WriteLine("发生错误,程序结束。");
exit();
}
Console.Write(G.vertices[j].data);
count++;
for(p=G.vertices[j].firstarc;p!=NULL;p=p.nextarc)
{
k=p.adjvex;
if (!(--indegree[k]))
Push(G.vertices[k]);
}
}
if (count<G.num)
Cosole.WriteLine("该图有环,出现错误,无法排序。");
else
Console.WriteLine("排序成功。");
}
----------------------------------------Code--------------------------------------
算法的时间复杂度O(n+e)。
Ⅶ 冒泡排序java是
冒泡排序算法:
int类型的数组:3 1 6 2 5
算法:取出最大的放在最后,下次就不用比较最后一个了。*/
public class BubbleSort{
public static void main(String[] args){
int[] a = {3,1,6,2,5};
//开始排序
for(int i=a.length-1;i>0;i--){
for(int j=0;j<i;j++){
if(a[j]>a[j+1]){
//交换位置
int temp;
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
//遍历
for(int i=0;i<a.length;i++){
System.out.println(a[i]);
}
算法原理
冒泡排序算法的运作如下:(从后往前)
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。