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]);
}
演算法原理
冒泡排序演算法的運作如下:(從後往前)
比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對。在這一點,最後的元素應該會是最大的數。
針對所有的元素重復以上的步驟,除了最後一個。
持續每次對越來越少的元素重復上面的步驟,直到沒有任何一對數字需要比較。