日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java中的排序算法——简单选择排序,树形选择排序与堆排序(一)

發布時間:2025/4/16 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java中的排序算法——简单选择排序,树形选择排序与堆排序(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
package com.sort;


/**
?* 選擇排序:
?* 簡單選擇排序,樹形選擇排序與堆排序
?*?
?*/
public class SelecSortDemo {

/**
* --------------------------------------------
* 簡單選擇排序
* 原理:假設列表中有n個元素,從第一個元素開始,在第一個元素
* 與最后一個元素之間選擇一個最小的元素與第一個元素交換,
* 然后從第二個元素開始,在第二個元素與最后一個元素之間選擇
* 最小的元素與第二個元素交換,以此類推,最后列表有序。
*/
public static void simpleSelectSort(Object[] a){
int len = a.length;
for(int i = 0,j;i<len;i++){
j = selectMin(a, i);
if(i!=j) //等于就沒有必要交換了
a[i] = a[j];
}
}
/**
* 簡單選擇排序的輔助方法
* 從指定位置i開始到最后位置選擇出一個最小的元素
* 并且返回它的索引值
*/
private static int selectMin(Object[] a,int low){
int min = low; //假設第一個元素為最小值
for(int i = low+1;i<a.length;i++){
if(((Comparable)a[i]).compareTo(a[min])<0){
min = i;
}
}
return min;
}



/**?
? ? ?* ---------------------------------------?
? ? ?* 樹形選擇排序 :
? ? ?* 對于簡單排序來說,主要是進行n-1趟元素的比較,每趟比較n-2次,
? ? ?* 每趟比較取出一個最小值(也可以是最大值),逐步使列表有序。
? ? ?* 但是第一趟的比較是可以為后續的比較提供信息的,使后續的比較次數大大減少,
? ? ?* 而后續的比較又可以為更后續的比較提供信息,這樣就減少了比較的次數,減少了
? ? ?* 時間復雜度。
? ? ?*?
? ? ?* 實現原理:
? ? ?* 第一步,首先對n個記錄進行兩兩比較,得到較小的n/2個數再依次比較,依次類推
? ? ?* 直到得到一個最小值,這是一個構造完全二叉樹的過程,根節點即為最小元素,葉子節點為列表元素。
? ? ?* 構造的此樹的存儲結構可以用數組表示方法,數組長度為2n-1。填充此樹,比如
? ? ?* 列表元素為:49 ? ?38 ? ? 65 ? ?97 ? 76 ? ?13 ? ?27 ? 49
? ? ?* 構造的樹為: ? ? ? ? ? ? ? ? ? ? 13
? ? ?* ? ? ? ? ? ? ? ? ? ? 38 ? ? ? ? ? ? ? 13
? ? ?* ? ? ? ? ? ? ? ?38 ? ? ? 65 ? ? ? 13 ? ? ? 27
? ? ?* ? ? ? ? ? ? ?19 ?38 ? 65 ?97 ? 76 ?13 ? 27 ?49
? ? ?* 13為根結點位最小值,列表元素為葉子節點
? ? ?*?
? ? ?* 第二步,移走最小元素,此時可重新為數組a的第一個位置賦值為此最小值,
? ? ?* 之后如果找出次小值則可以為第二個位置賦值,......
? ? ?*?
? ? ?* 第三步,找出次小值,找出最小值在葉子節點的位置,從該節點開始,和其兄弟節點
? ? ?* 進行比較,修改從葉子節點到根節點的元素值,比較完畢后,根節點為次小值。
? ? ?* 第三步比較是利用了第一次比較提供的信息,因為第一步已經得到了兩兩比較的
? ? ?* 較小值,只要拿第一次與最小值比較的元素(即最小值的兄弟節點)與它們比較即可得最小值。
? ? ?* 即拿上述例子的76與27比較,然后27與38比較得到次小值27。
? ? ?* 重復第二和第三步,排序完成。
? ? ?*?
? ? ?* PS:這里把移出去的葉子節點都要重設為最大值,可對此方法進行稍微改動
? ? ?* 可傳一個最大值進來,這里是整型所以用了Integer.MAX_VALUE
? ? ?*/ ?
? ? public static void treeSelectSort(Object[] a){ ?
? ? ? ?int len = a.length;
? ? ? ?int treeSize = 2 * len - 1; //完全二叉樹的節點數
? ? ? ?int low = 0;
? ? ? ?Object[] tree = new Object[treeSize]; //臨時的樹存儲空間
? ? ? ?//由后向前填充此樹,索引從0開始
? ? ? ?for(int i = len-1,j=0 ;i >= 0; --i,j++){ //填充葉子節點
? ? ? tree[treeSize-1-j] = a[i];
? ? ? ?}
? ? ? ?
? ? ? ?for(int i = treeSize-1;i>0;i-=2){ //填充非終端節點
? ? ? tree[(i-1)/2] = ((Comparable)tree[i-1]).compareTo(tree[i]) < 0 ? tree[i-1]:tree[i];
? ? ? ?}
? ? ? ?
? ? ? ?//不斷移走最小節點
? ? ? ?int minIndex;
? ? ? ?while(low < len){
? ? ? Object min = tree[0]; //最小值
? ? ? a[low++] = min;
? ? ? minIndex = treeSize-1;
? ? ? //找到最小值的索引
? ? ? while(((Comparable)tree[minIndex]).compareTo(min)!=0){
? ? ? minIndex--;
? ? ? }
? ? ? tree[minIndex] = Integer.MAX_VALUE; //設置一個最大值標志
? ? ? //找到其兄弟節點
? ? ? while(minIndex > 0){ //如果其還有父節點
? ? ? if(minIndex % 2 == 0){ //如果是右節點
? ? ? tree[(minIndex-1)/2] = ((Comparable)tree[minIndex-1]).compareTo(tree[minIndex])
? ? ? < 0 ? tree[minIndex-1]:tree[minIndex];
? ? ? minIndex = (minIndex-1)/2;
? ? ? }else{ //如果是左節點
? ? ? ?tree[minIndex/2] = ((Comparable)tree[minIndex]).compareTo(tree[minIndex+1])
? < 0 ? tree[minIndex]:tree[minIndex+1];
? minIndex = minIndex/2;
? ? ? }
? ? ? }
? ? ??
? ? ? ?}
? ? }




? ??
? ? /**
* ----------------------------------
* 堆排序
* ? ?堆排序是在樹形選擇排序的基礎上進一步進行優化
* 只需要一個額外的存儲空間,且不需根據標志判斷是不是最大值。
* 堆的定義:在1到n/2的元素中,有k(i)<=k(2i),k(i)<=k(2i+1)
* 或k(i)>=k(2i),k(i)>=k(2i+1)
* 簡單來說:就是假如將此序列看成一棵完全二叉樹,要使這個無序列表
* 變成堆,則小于等于n/2(最后一個非終端節點就是n/2)的某個節點i的左右子節點均大于此節點,
* 即堆的定義k(i)<=k(2i),k(i)<=k(2i+1)。
*?
* 實現原理:
* ? ?首先將序列看成一個樹形結構,
* 1.構建堆的過程:找到最后一個非終端節點n/2,與它的左右子節點比較,
* 比較結果使此父節點為這三個節點的最小值。再找n/2-1這個節點,
* 與其左右子節點比較,得到最小值,以此類推....,最后根節點即為最小值
* 比如:49 ?38 ? 65 ? 97 ? 76 ? 13 ? 27 ? 49
* 初始樹為:
* ? ? ? ? ? ? ?49
* ? ? ? ?38 ? ? ? ? ? ? ?65
* ? ?97 ? ? ?76 ? ? ?13 ? ? ? 27
* 49
* 構造堆后的樹為
* ? ? ? ? ? ? ?13
* ? ? ? 38 ? ? ? ? ? ? ?27
* ? ?49 ? ?76 ? ? ? 65 ? ? ? 49
* ?97
* ?交換數據的順序為:97<——>49, 13<--->65,38不用換,49<-->13,13<-->27
* 2.輸出堆頂元素并調整建新堆的過程
* ?輸出堆頂最小值后,假設以最后一個值替代之,由于其左右子樹的堆結構并沒有被破壞
* 只需要自上而下進行調整。比如把上圖的13輸出后以97替代,然后可以把97與27交換,
* 然后97又與49交換,此時最小值為根元素27,輸出27后以又用最后一個值替換根元素,
* 以此類推,則最終得到有序序列?
*/
public static void heapSort(Object[] a){ ?
? ? ? ? int len = a.length; ?
? ? ? ? //構建堆 ?
? ? ? ? for(int i=(len-1)/2;i>=0;i--){ ?
? ? ? ? ? ? heapAdjust(a,i,len); ?
? ? ? ? } ?
? ? ? ? ??
? ? ? ? //輸出堆頂元素并調整建新堆的過程 ?
? ? ? ? int count = len-1; ?
? ? ? ? while(count > 0 ){ ?
? ? ? ? ? ? //交換樹根與最后一個值 ?
? ? ? ? ? ? swap(a,0,count); ?
? ? ? ? ? ? count -- ; ?
? ? ? ? ? ? heapAdjust(a,0,count); ?
? ? ? ? } ?
? ? } ?
? ? ??
? ? /**?
? ? ?* 調整某一個節點極其左右子節點的位置 ,并選擇左右節點中的較大者
? ? ?* 繼續向下調整
? ? ?*/ ?
? ? private static void heapAdjust(Object[] a,int i,int len){ ?
? ? Object parent = a[i];
? ? for(int j = (i+1) * 2 - 1;j < len; j = (j+1) * 2 - 1){ //沿著左右節點中的較小者繼續往下搜索
? ? if(j < len-1 && ((Comparable)a[j]).compareTo(a[j+1]) < 0 ){
? ? ++j; //如果左節點較大過度到右節點
? ? }
? ? if(((Comparable)parent).compareTo(a[j]) > 0) //左右節點均小于父節點則不必要繼續向下搜索
? ? break;
? ? a[i] = a[j];
? ? i = j ;
? ? }
? ? ? ? a[i] = parent; //parent插入到正確的位置
? ? ? ??
? ? }

/**
* 交換數組中兩元素的值
*/
private static void swap(Object[] a,int i,int j){
Object temp = null;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
? ??
? ? //just for test
? ? public static void main(String[] args) {
? ? Integer[] data = {49,38,65,97,76,13,27,49};
SelecSortDemo.treeSelectSort(data);
for(Integer d:data){
System.out.println(d);
}

}


轉自:http://zhouyunan2010.iteye.com/blog/1217462

}

總結

以上是生活随笔為你收集整理的java中的排序算法——简单选择排序,树形选择排序与堆排序(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。