1. 程式人生 > >“深入理解”—選擇排序演算法

“深入理解”—選擇排序演算法

選擇排序演算法有兩種:直接選擇排序和堆排序

1、直接選擇排序(Straight Select Sort)演算法思想:第一趟從n個元素的資料序列中選出關鍵字最小/大的元素並放在最前/後位置,下一趟從n-1個元素中選出最小/大的元素並放在最前/後位置。以此類推,經過n-1趟完成排序。

示例如下:

	//選擇排序
	public static void selectsort(int[] a)
	{
		int temp;
		for(int i=0;i<a.length;i++)
		{
			//內層迴圈j=i+1,外層迴圈控制著迴圈次數。即每趟中a[i]這個值就是本趟的最小值。i位置上是最小值
			for(int j=i+1;j<a.length;j++)   
			{
				if(a[i]>a[j])
				{
					temp=a[i];
					a[i]=a[j];
					a[j]=temp;
				}
			}
		}
	}


2、堆排序:

堆排序涉及到完全二叉樹的概念。堆是一個完全二叉樹,分為大頂堆和小頂堆兩種。

大頂堆:每個節點的值都大於或等於其左右孩子節點的值。如圖(1)所示:

小頂堆:每個節點的值都小於或等於其左右孩子節點的值。如圖(2)所示:

                        

                                        圖 (1) 大頂堆                                                                                                          圖( 2) 小頂堆

堆排序演算法的定義:

        堆排序(Heap Sort)就是利用堆(假設為大頂堆)進行排序的方法。其基本思想是:將待排序的序列構造成一個大頂堆,此時整個序列的最大值就是堆頂的根節點。將它移走(其實就是將其與堆陣列的末尾元素交換,此時末尾元素就是最大值),然後將剩餘的 N -1個元素重新構造成一個堆,這樣就會得到N個元素中的次小值。如此反覆執行,最後將得到一個有序序列。

堆排序完整程式碼如下:

public class TestHeapSort {
	
	public static void main(String[] args){
		
		int[] arr={3,1,2,4,7,6,5,9,8,10};
		HSort(arr);
		
		for(int a:arr)
		   System.out.print(a+" ");
	}
	// 堆排序
	//進行堆排序方法  
    private static void HSort(int[] arr){  
        //1、構建大頂堆  
        for(int parent=(arr.length-1)/2;parent>=0;parent--){  
            MaxHeap(arr,parent,arr.length-1);  
        }  
        for(int t=arr.length-1;t>0;t--){  
            swap(arr,0,t); //交換資料  
            MaxHeap(arr, 0, t-1);   //根節點從0開始,繼續構建大頂堆。  
        }  
    }  
    //交換資料方法  
    private static void swap(int[] arr, int i, int t) {  
        int temp=arr[i];  
        arr[i]=arr[t];  
        arr[t]=temp;  
    }  
    /* 
     * 構建大頂堆的方法 
     * s 代表擁有左右孩子節點的節點,即本次要調整位置的節點 
     * m 代表當前堆的長度 
     */  
    private static void MaxHeap(int[] arr, int s, int m) {  
        int temp,j;  
        temp=arr[s];  
        for(j=2*s+1;j<=m;j=2*j+1){   //j=2*s+1為s節點的左孩子,j+1為s節點的右孩子  
                                     //j=2*j+1是要找到j的孩子節點  
            if(j<m&&arr[j]<arr[j+1])  
                j++;     //將j指向當前左右孩子節點中的較大值  
            if(temp>arr[j])  
                break;  //如果s節點的值大於其最大的孩子節點值,則,迴圈結束,本次不做任何改變  
            arr[s]=arr[j];  //否則將較大的孩子節點的值賦值給父節點  
            s=j;    //將j的值賦值給s,即j成為了下一波的父節點,繼續比較  
        }  
        arr[s]=temp;  //迴圈結束  
    }  
	
}

在第一次構建大頂堆時,我們int parent = (arr.length-1)/2,也就是父節點從arr[4] = 7開始,4、3、2、1 、0都存在孩子節點。

官方一點就是:我們從最下層最右邊的非終端節點開始構建,將其與其孩子節點進行比較和若有必要的互換,對於每個非終端節點來說,其實最多進行兩次比較和互換操作,因此整個構建堆的時間複雜度為O(N)。

在正式排序時,第i 次取堆頂記錄重建堆需要O(logi)的時間,(完全二叉樹的某個節點到根節點的距離為logi+1),並且需要取n-1次堆頂記錄,因此,重建堆的時間複雜度為O(nlogN)

故,總體上堆排序的時間複雜度為O(nlogn)。



從程式碼中可以看出:

      排序過程分為兩個for迴圈,第一個迴圈完成了將一個帶排序序列構建成了一個大頂堆。第二個迴圈完成逐步將每個最大值的根節點與末尾元素交換,並且再次調整其為大頂堆。

相關推薦

深入理解”—選擇排序演算法

選擇排序演算法有兩種:直接選擇排序和堆排序1、直接選擇排序(Straight Select Sort)演算法思想:第一趟從n個元素的資料序列中選出關鍵字最小/大的元素並放在最前/後位置,下一趟從n-1個

深入理解”—歸併排序演算法

歸併排序:  歸併排序 (merge sort) 是一類與插入排序、交換排序、選擇排序不同的另一種排序方法。歸併的含義是將兩個或兩個以上的有序表合併成一個新的有序表。如圖所示:import java.u

最易於理解排序演算法——選擇排序

我在標題中說選擇排序是最易於理解的演算法,下面就來給大家說說為何選擇排序是最易於理解的演算法。 思想:                 以升序為例,在陣列arr中遍歷陣列找到其中最小的那個元素,將其與arr[0]交換,之後在剩餘的陣列中,在尋找最小的元素,將其與arr[1

(排序演算法)linux c語言實現選擇排序演算法(氣泡排序的略微改進版)

 快速排序演算法和氣泡排序演算法是差不多的,都是要兩層迴圈,外迴圈是要比較的個數,其實就是元素的個數,內迴圈就是外層那個標記和其他的比較大小, 氣泡排序是相鄰的兩個,兩兩比較,最後交換出一個最大或者最小值, 快速排序是在氣泡排序的基礎上,找出那個最小的或者最大的,但是不是直接交換,

深入理解線性迴歸演算法(二):正則項的詳細分析

前言 當模型的複雜度達到一定程度時,則模型處於過擬合狀態,類似這種意思相信大家看到個很多次了,本文首先討論了怎麼去理解複雜度這一概念,然後回顧貝葉斯思想(原諒我有點囉嗦),並從貝葉斯的角度去理解正則項的含義以及正則項降低模型複雜度的方法,最後總結全文。     &nb

深入理解線性迴歸演算法(三):淺談貝葉斯線性迴歸

前言 上文介紹了正則化項與貝葉斯的關係,正則化項對應於貝葉斯的先驗分佈,因此通過設定引數的先驗分佈來調節正則化項。本文首先介紹了貝葉斯線性迴歸的相關性質,和正則化引數λ的作用,然後簡單介紹了貝葉斯思想的模型比較,最後總結全文。   目錄 1、後驗引數分佈和預測變數分

利用指標排序選擇排序演算法

  1 //讀入字串,並排序字串 2 #include <stdio.h> 3 #include <string.h> 4 #define SIZE 81 5 #define LIM 20 6 #define HALT "" 7 8 void sts

演算法(1) 選擇排序演算法 java

簡介:選擇排序是一個時間複雜度為O(N^2)的基本排序演算法,當然也有其適用的場景,比如說該演算法的易於實現的特性,可應用於對某些實際問題的快速實現上. 原理:從未排序的資料中,選出最小的資料,然後與未排序的第一個資料進行比較交換操作,直到所有的資料都排好序. 步驟: ①在未進行排

排序演算法選擇排序演算法【java實現】

簡介:遍歷陣列,每次選出最小的數與索引第一個進行交換,直到全部完成。 package zhgyu.sort; /** /*選擇排序演算法 * @author zhgyu * */ public class SelectionSort { static final int SIZE =

氣泡排序選擇排序演算法的實現(c/c++)

一 選擇排序:   選擇排序的工作原理是從 待排序的元素中選出最小或者最大的一個元素,存放在序列的起始位置,直到全部待排序的元素排完。這是一種不穩定的排序方法。比氣泡排序快。 二 氣泡排序:   氣泡排序重複訪問要排序的元素,依次比較兩個相鄰的元素。如果前一個元素大於

演算法學習之選擇排序演算法的python實現

  ——參考自《演算法圖解》 1 def findSmallest(arr): 2 # 假設第一個元素最小 3 smallest = arr[0] 4 smallest_index = 0 5 for i in range(1,len(arr)): 6

選擇排序演算法

選擇排序原理 一串無序序列,從陣列的最左端開始向右逐個查詢比較。初始第一次操作,陣列中首元素計做基準元素,從第二個元素開始向右逐個與第一個元素進行大小比較。找到小於首元素的變數,然後記住該元素所在的位置。與第一個元素進行交換,然後繼續之前類似操作。這次

簡單選擇排序演算法原理及java實現(超詳細)

選擇排序是一種非常簡單的排序演算法,就是在序列中依次選擇最大(或者最小)的數,並將其放到待排序的數列的起始位置。 簡單選擇排序的原理 簡單選擇排序的原理非常簡單,即在待排序的數列中尋找最大(或者最小)的一個數,與第 1 個元素進行交換,接著在剩餘的待排序的數列中繼續找最大(最小)的一個數,與第 2 個元素交

資料結構和演算法 | 簡單選擇排序演算法原理及實現

選擇排序是一種非常簡單的排序演算法,就是在序列中依次選擇最大(或者最小)的數,並將其放到待排序的數列的起始位置。 簡單選擇排序的原理 簡單選擇排序的原理非常簡單,即在待排序的數列中尋找最大(或者最小)的一個數,與第 1 個元素進行交換,接著在剩餘的待排序的數列

(排序演算法)linux c語言實現選擇排序演算法

/*************************************************** ##filename : arrinsert.c ##author : GYZ ##

深入理解線性迴歸演算法(一)

前言 線性迴歸演算法是公眾號介紹的第一個機器學習演算法,原理比較簡單,相信大部分人對線性迴歸演算法的理解多於其他演算法。本文介紹的線性迴歸演算法包括最小二乘法和最大似然法,進而討論這兩種演算法蘊含的一些小知識,然後分析演算法的偏差和方差問題,最後總結全文。        

選擇排序演算法詳解

基本思想: 在要排序的一組數中,選出最小的一個數與第一個位置的數交換;然後在剩下的數當中再找最小的與第二個位置的數交換,如此迴圈到倒數第二個數和最後一個數比較為止。     實現: public static void selectSort(in

簡單選擇排序演算法JAVA實現

簡單選擇排序的過程為:第1次,從n個記錄中找出關鍵碼最小的記錄與第1個記錄交換,第2次,,從第2個記錄開始的n-1個記錄中再選出關鍵碼最小的記錄與第2個記錄交換;如此,第i次,則從第i個記錄開始的n-i+1個記錄中選出關鍵碼最小的記錄與第i個記錄交換,直到整個序列按關鍵碼有序。 例:3,1,4,

equals()和HashCode()深入理解以及Hash演算法原理

1.深入理解equals(): 在我的一篇部落格“==”和.equals()的區別中向讀者提出提醒: Object類中的equals方法和“==”是一樣的,沒有區別,即倆個物件的比較是比較他們的棧記憶體中儲存的記憶體地址。而String類,Integer類等等一些類,是

python實現選擇排序演算法

什麼是選擇排序請看:排序演算法:氣泡排序和選擇排序的內容,區別與優缺點。 __author__ = "PoHu" __copyright__ = "PoHu 2018" __version__ = "1.0.0" __license__ = "Henu" def findSmal