黄色网址大全免费-黄色网址你懂得-黄色网址你懂的-黄色网址有那些-免费超爽视频-免费大片黄国产在线观看

面試題首頁(yè) > 排序面試題

排序面試題

001什么是冒泡排序?

冒泡排序是在遍歷數(shù)組的過程中,每次都要比較連續(xù)相鄰的元素,如果某一對(duì)相鄰元素是降序(即前面的數(shù)大于后面的數(shù)),則互換它們的值,否則,保持不變。由于較大的值像“氣泡”一樣逐漸浮出頂部,而較小的值沉向底部,所以叫冒泡排序。

002冒泡排序的代碼實(shí)現(xiàn)?

具體實(shí)現(xiàn)參考如下源代碼:

//冒泡排序
public static void bubbleSort(int[] list){
    int n=list.length;
    for(int i=1;i<n;i++){//總共比較n-1趟
        for(int j=0;j<n-i;j++){//第i趟比較n-i次
            if(list[j]>list[j+1]){
                int temp;
                temp=list[j];
                list[j]=list[j+1];
                list[j+1]=temp;				
            }
        }

        System.out.print("第"+(i)+"輪排序結(jié)果:");  
        display(list);
    }
}

003冒泡排序時(shí)間復(fù)雜度?

冒泡排序的時(shí)間復(fù)雜度是O(N2)。 假設(shè)被排序的數(shù)列中有N個(gè)數(shù)。遍歷一趟的時(shí)間復(fù)雜度是O(N),需要遍歷多少次呢? N-1次!因此,冒泡排序的時(shí)間復(fù)雜度是O(N2)。

004冒泡排序穩(wěn)定性?

冒泡排序是穩(wěn)定的算法,它滿足穩(wěn)定算法的定義。所謂算法穩(wěn)定性指假設(shè)在數(shù)列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。則這個(gè)排序算法是穩(wěn)定的!

005冒泡排序的改進(jìn)版實(shí)現(xiàn)。

/*
 * 冒泡排序(改進(jìn)版)
 *
 * 參數(shù)說明:
 *     a -- 待排序的數(shù)組
 *     n -- 數(shù)組的長(zhǎng)度
 */
public static void bubbleSort2(int[] a, int n) {
    int i, j;
    int flag; // 標(biāo)記

    for (i = n - 1; i > 0; i--) {

        flag = 0; // 初始化標(biāo)記為0
        // 將a[0...i]中最大的數(shù)據(jù)放在末尾
        for (j = 0; j < i; j++) {
            if (a[j] > a[j + 1]) {
                // 交換a[j]和a[j+1]
                int tmp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = tmp;

                flag = 1; // 若發(fā)生交換,則設(shè)標(biāo)記為1
            }
        }

        if (flag == 0)
            break; // 若沒發(fā)生交換,則說明數(shù)列已有序。
    }
}

006什么是選擇排序?

選擇排序是在遍歷一個(gè)待排序的數(shù)組過程中,

第一次從 arr[0] 到 arr[n-1] 中選取最小值,與 arr[0] 交換;

第二次從arr[1] 到 arr[n-1]中選取最小值, 與arr[1]交換;

第三次從arr[2] 到 arr[n-1]中選取最小值,與arr[2]交換;

……

第 i 次從 arr[i-1] 到 arr [n-1] 中選取最小值,與arr[i-1]交換;

第n-1次從 arr[n-2] 到 arr [n-1] 中選取最小值,與 arr[n-2] 交換,總共通過n-1次,得到一個(gè)按排序碼從小到大排列的有序序列。

007選擇排序的代碼實(shí)現(xiàn)?

具體實(shí)現(xiàn)參考如下源代碼:

public static void choice(int arr[]) {
    for (int i = 0; i < arr.length - 1; i++) {
        int minIndex = i;
        int min = arr[i];
        for (int j = i + 1; j < arr.length; j++) {
            if (min > arr[j]) {
                min = arr[j];
                minIndex = j;
            }
        }
        if (minIndex != i) {
            arr[minIndex] = arr[i];
            arr[i] = min;
        }
    }
}

008有一組數(shù)據(jù)“12,15,1,18,2,35,30,11”,用選擇法由小到大排序,第2趟交換數(shù)據(jù)后數(shù)據(jù)的順序是( )。

A. 11,1,2,12,35,18,30,15
B. 1,2,12,18,15,35,30,11
C. 1,2,11,12,15,18,30,35
D. 1,2,11,12,15,18,35,30
答案:B
解析:第一趟選擇1,將1和12交換位置,序列變?yōu)?,15,12,18,2,35,30,11,第二趟選擇2,將2和15交換位置,序列變?yōu)?,2,12,18,15,35,30,11;故B正確

009在選擇排序中,以下什么情況下選擇排序會(huì)更快執(zhí)行?

A. 數(shù)據(jù)已按升序排列
B. 數(shù)據(jù)已按升降序排列
C. 倆者花費(fèi)時(shí)間一樣
答案:C
解析:不管升序還是降序 其比較次數(shù)都是整條路徑。

010什么是插入排序?

1)插入排序是把n個(gè)待排序的元素看成為一個(gè)有序表和一個(gè)無(wú)序表,開始時(shí)有序表中只包含一個(gè)元素,無(wú)序表中包含有n-1個(gè)元素,排序過程中每次從無(wú)序表中取出第一個(gè)元素,將它插入到有序表中的適當(dāng)位置,使之成為新的有序表,重復(fù)n-1次可完成排序過程。

2)具體流程如下:

【1】把數(shù)組分成有序a[0]和無(wú)序a[1~7]范圍,有序中就一個(gè)數(shù)肯定是有序的不用管。

【2】把數(shù)組分成有序a[0~1]和無(wú)序a[2~7]范圍,有序中讓a[1]和a[0]范圍比較,如果a[1]大于a[0],不用交換;如果a[1]小于a[0],交換位置,這樣a[0~1]就是有序的。

【3】把數(shù)組分成有序a[0~2]和無(wú)序a[3~7]范圍,有序中讓a[2]和a[0~1]范圍比較。如果a[2]大于a[1],不用交換;如果a[2]小于a[1],交換位置;周而復(fù)始再讓a[1]和a[0]比較,這樣a[0~2]就是有序的。

【4】把數(shù)組分成有序a[0~3]和無(wú)序a[4~7]范圍,有序中讓a[3]和a[0~2]范圍比較。如果a[3]大于a[2],不用交換;如果a[3]小于a[2],交換位置;周而復(fù)始再讓a[2]和a[1]比較........這樣a[0~3]就是有序的。

【5】把數(shù)組分成有序a[0~4]和無(wú)序a[5~7]范圍,有序中讓a[4]和a[0~3]范圍比較。如果a[4]大于a[3],不用交換;如果a[4]小于a[3],交換位置;周而復(fù)始再讓a[3]和a[2]比較........這樣a[0~4]就是有序的。

...... 就這樣依次比較到最后一個(gè)元素,通俗的說就是一路向左交換。

011插入排序的代碼實(shí)現(xiàn)?

public static void insertSort(int[ ] arr){
    if(arr==null||arr.length<2){
        return;
    }
    //0~0有序的
    //0~i有序
    for(int i=1;i<arr.length;i++){
        for(int j=i-1;j>=0&&arr[j]>arr[j+1];j--){
            swap(arr,j,j+1);
        }
    }
}

012設(shè)一組初始記錄關(guān)鍵字的長(zhǎng)度為8,則最多經(jīng)過( )趟插入排序可以得到有序序列。

A. 6
B. 7
C. 8
D. 9
答案:B
解析:第i趟插入排序可以使前i個(gè)元素為n個(gè)元素中前i小且有序,執(zhí)行n-1次后前n-1個(gè)元素為n個(gè)元素中前n-1小且有序,第n個(gè)元素同時(shí)也處于正確的位置,故只需n-1趟插入排序。

013什么是希爾排序?

1)希爾排序又稱遞減增量排序算法,是插入排序的改進(jìn)版。它與插入排序的不同之處在于,它會(huì)優(yōu)先比較距離較遠(yuǎn)的元素。希爾排序的基本思想是:先將整個(gè)待排序的記錄序列分割成為若干子序列分別進(jìn)行直接插入排序,待整個(gè)序列中的記錄"基本有序"時(shí),再對(duì)全體記錄進(jìn)行依次直接插入排序。希爾排序目的為了加快速度改進(jìn)了插入排序,交換不相鄰的元素對(duì)數(shù)組的局部進(jìn)行排序,并最終用插入排序?qū)⒕植坑行虻臄?shù)組排序。在此我們選擇增量 gap=length/2,縮小增量以 gap = gap/2 的方式,用序列 {n/2,(n/2)/2...1} 來(lái)表示。

2) 算法圖解

【1】下面數(shù)組的長(zhǎng)度length為8,初始增量第一趟 gap = length/2 = 4,即讓第1個(gè)數(shù)和第5個(gè)數(shù)比較,第2個(gè)數(shù)和第6個(gè)數(shù)進(jìn)行比較,第3個(gè)數(shù)和第7個(gè)數(shù)進(jìn)行比較,第4個(gè)數(shù)和第8個(gè)數(shù)進(jìn)行比較,最終結(jié)果是【1 5 2 3 7 6 9 4】

【2】第二趟,gap=gap/2=2,增量縮小為 2。即讓第1個(gè)數(shù)、第3個(gè)數(shù)、第5個(gè)數(shù)和第7個(gè)數(shù)進(jìn)行比較,第2個(gè)數(shù)、第4個(gè)數(shù)、第6個(gè)數(shù)和第8個(gè)數(shù)進(jìn)行比較,最終結(jié)果是【1 3 2 4 7 5 9 6】

【3】第三趟,gap=gap/2=1,增量縮小為 1。所有的數(shù)進(jìn)行比較得到的結(jié)果【1 2 3 4 5 6 7 9】

014希爾排序的代碼實(shí)現(xiàn)?

public static void shellSort(int[] args) {
    for (int gap = args.length / 2; gap > 0; gap /= 2) {
        // 從第gap個(gè)元素,逐個(gè)對(duì)其所在組進(jìn)行直接插入排序操作
        for (int i = gap; i < args.length; i++) {
            int j = i;
            int temp = args[j];
            if (args[j] < args[j - gap]) {
                while (j - gap >= 0 && temp < args[j - gap]) {
                    // 移動(dòng)法
                    args[j] = args[j - gap];
                    j -= gap;
                }
                args[j] = temp;
            }
        }    
    }
}    

015希爾排序的組內(nèi)排序采用的是( )。

A. 直接插入排序
B. 折半插入排序
C. 快速排序
D. 歸并排序
答案: A  
解析: 希爾排序的思想是:先將待排元素序列分割成若干個(gè)子序列(由相隔某個(gè)“增量”的元素組成),分別進(jìn)行直接插入排序,然后依次縮減增量再進(jìn)行排序,待整個(gè)序列中的元素基本有序(增量足夠小)時(shí),再對(duì)全體元素進(jìn)行一次直接插入排序。

016設(shè) 一組初始記錄關(guān)鍵字序列為(50,40,95,20,15,70,60,45),則以增量d=4的一趟希爾排序結(jié)束后前4條記錄關(guān)鍵字為( )。

A.  40,50,20,95
B.  15,40,60,20
C.  15,20,40,45
D.  45,40,15,20
答案: B
解析:希爾排序?qū)儆诓迦腩惻判颍菍⒄麄€(gè)有序序列分割成若干小的子序列分別進(jìn)行插入排序。排序過程是先取一個(gè)正整數(shù)d1<n,把所有序號(hào)相隔d1的數(shù)組元素放一組,組內(nèi)進(jìn)行直接插入排序;然后取d2<d1,重復(fù)上述分組和排序操作;直至di = 1,即所有記錄放進(jìn)一個(gè)組中排序?yàn)橹埂?br /> 題目中:d = 4,排序之后為:15,40,60,20,50,70,95,45
              d = 2,排序之后為:15,20,50,40,60,45,95,70
              d = 3,排序之后為:15,20,40,45,50,60,70,95

017什么是歸并排序?

1)歸并排序采用了分治策略(divide-and-conquer),就是將原問題分解為一些規(guī)模較小的相似子問題,然后遞歸解決這些子問題,最后合并其結(jié)果作為原問題的解。

2)算法圖解

【1】如圖:先將數(shù)組分兩半,左邊是【2、9、5、4】,右邊是【8、1、6、7】;

【2】將左邊【2、9、5、4】繼續(xù)分兩半,左邊是【2、9】,右邊是【5、4】;

【3】將【2、9】繼續(xù)分兩半,左邊是【2】,右邊是【9】;將【5、4】繼續(xù)分兩半,左邊是【5】,右邊是【4】;

【5】創(chuàng)建臨時(shí)輔助數(shù)組,將左邊【2】和右邊【9】通過比較大小進(jìn)行合并【2、9】;

【6】創(chuàng)建臨時(shí)輔助數(shù)組,將左邊【5】和右邊【4】通過比較大小進(jìn)行合并【4、5】;

【7】創(chuàng)建臨時(shí)輔助數(shù)組,將左邊【2、9】和右邊【4、5】通過比較大小進(jìn)行合并【2、4、5、9】,同樣的道理得到【1、8、6、7】;

【8】創(chuàng)建臨時(shí)輔助數(shù)組,將左邊【2、4、5、9】和右邊【1、8、6、7】通過比較大小進(jìn)行合并【1、2、4、5、6、7、8、9】;

018歸并排序的代碼實(shí)現(xiàn)?

public static void mergeSort(int[] arr) { 
    if (arr == null || arr.length < 2) {
	    return;
    }
    process(arr, 0, arr.length - 1);
}
public static void process(int[] arr, int L, int R) {
    if (L == R) {
	    return;
	}
	int mid = L + ((R - L) >> 1);
	process(arr, L, mid);
	process(arr, mid + 1, R);
	merge(arr, L, mid, R);
}
public static void merge(int[] arr, int L, int M, int R) {		
    int[] help = new int[R - L + 1];
	int i = 0;
	int p1 = L;
	int p2 = M + 1;
	while (p1 <= M && p2 <= R) {
		help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
	}
	while (p1 <= M) {
		help[i++] = arr[p1++];
	}
	while (p2 <= R) {
		help[i++] = arr[p2++];
	}
	for (i = 0; i < help.length; i++) {
		arr[L + i] = help[i];
	}
}

019關(guān)于歸并排序敘述正確的是( ).

A. 歸并排序使用了分治策略的思想
B. 歸并排序使用了貪心策略的思想
C. 子序列的長(zhǎng)度一定相等
D. 歸并排序是穩(wěn)定的
答案:AD
解析:暫無(wú)解析

020若外部存儲(chǔ)上有3110400個(gè)記錄,做6路平衡歸并排序,計(jì)算機(jī)內(nèi)存工作區(qū)能容納400個(gè)記錄,則排序好所有記錄,需要作幾趟歸并排序( )

A. 6
B. 3
C. 5
D. 4
答案:C
解析:每次將工作區(qū)裝滿,共計(jì)3110400/400=7776個(gè)歸并段,對(duì)于n路歸并排序,m個(gè)歸并段,需要?dú)w并排序的次數(shù)為次,代入數(shù)據(jù)得到答案為5,所以C正確。

021什么是快速排序?

1)快排問題和荷蘭國(guó)旗問題類似,快速排序采用的思想是分治思想。主要分兩個(gè)步驟:

第一步:從要排序的數(shù)組中隨便找出一個(gè)元素作為基準(zhǔn)(pivot),然后對(duì)數(shù)組進(jìn)行分區(qū)操作,使基準(zhǔn)左邊元素的值都不大于基準(zhǔn)值,基準(zhǔn)右邊的元素值都不小于基準(zhǔn)值。

第二步就是對(duì)高段位和地段為兩部分進(jìn)行遞歸排序。

2)算法圖解

【1】從【5,3,5,6,2,7】數(shù)組中,隨機(jī)選取一個(gè)數(shù)(假設(shè)這里選的數(shù)是5)與最右邊的7進(jìn)行交換 ,如下圖

【2】準(zhǔn)備好以5為分界點(diǎn),三個(gè)區(qū)域分別為小于區(qū)、大于區(qū)(大于區(qū)包含最右側(cè)的一個(gè)數(shù))和等于區(qū),并準(zhǔn)備一個(gè)指針,指向最左側(cè)的數(shù),如下圖

【3】接下來(lái),每次操作都拿指針位置的數(shù)與5進(jìn)行比較,交換原則如下:

-----------------------------------------------------------

原則1:指針位置的數(shù)<5

拿指針位置的數(shù)與小于區(qū)右邊第一個(gè)數(shù)進(jìn)行交換

小于區(qū)向右擴(kuò)大一位

指針向右移動(dòng)一位

原則2:指針位置的數(shù)=5

指針向右移動(dòng)一位

原則3:指針位置的數(shù)>5

拿指針位置的數(shù)與大于區(qū)左邊第一個(gè)數(shù)進(jìn)行交換

大于區(qū)向左擴(kuò)大一位

指針位置不動(dòng)

-------------------------------------------------------

根據(jù)圖可以看出指針指向的第一個(gè)數(shù)是5,5=5,滿足交換原則2,指針向右移動(dòng)一位,如下圖

【4】從上圖可知,此時(shí)3<5,根據(jù)交換原則第1點(diǎn),拿3和5(小于區(qū)右邊第一個(gè)數(shù))交換,小于區(qū)向右擴(kuò)大一位,指針向右移動(dòng)一位,結(jié)果如下圖

【5】從上圖可以看出,此時(shí)7>5,滿足交換原則第3點(diǎn),7和2(大于區(qū)左邊第一個(gè)數(shù))交換,大于區(qū)向左擴(kuò)大一位,指針不動(dòng),如下圖

【6】從上圖可以看出,2<5,滿足交換原則第1點(diǎn),2和5(小于區(qū)右邊第一個(gè)數(shù))交換,小于區(qū)向右擴(kuò)大一位,指針向右移動(dòng)一位,得到如下結(jié)果

【7】從上圖可以看出,6>5,滿足交換原則第3點(diǎn),6和6自己換,大于區(qū)向左擴(kuò)大一位,指針位置不動(dòng),得到下面結(jié)果

【8】此時(shí),指針與大于區(qū)相遇,則將指針位置的數(shù)6與隨機(jī)選出來(lái)的5進(jìn)行交換,就可以得到三個(gè)區(qū)域:小于區(qū),等于區(qū),大于區(qū),周而復(fù)始完成最終的排序

022快速排序的代碼實(shí)現(xiàn)?

public static void quickSort(int[] arr) {
    if (arr == null || arr.length < 2) {
	    return;
	}
	quickSort(arr, 0, arr.length - 1);
}
// arr[l..r]排好序
public static void quickSort(int[] arr, int L, int R) {
    if (L < R) {
        swap(arr, L + (int) (Math.random() * (R - L + 1)), R);
		int[] p = partition(arr, L, R);
		quickSort(arr, L, p[0] - 1); // < 區(qū)
		quickSort(arr, p[1] + 1, R); // > 區(qū)
	}
}
// 這是一個(gè)處理arr[l..r]的函數(shù)
// 默認(rèn)以arr[r]做劃分,arr[r] -> p     <p   ==p   >p
// 返回等于區(qū)域(左邊界,右邊界), 所以返回一個(gè)長(zhǎng)度為2的數(shù)組res, res[0] res[1]
public static int[] partition(int[] arr, int L, int R) {
    int less = L - 1; // <區(qū)右邊界
    int more = R; // >區(qū)左邊界
    int index=L;
    while (index < more) { // L表示當(dāng)前數(shù)的位置   arr[R]  ->  劃分值
        if (arr[index] < arr[R]) { // 當(dāng)前數(shù)   <  劃分值
            swap(arr, ++less, index++);
        } else if (arr[index] > arr[R]) { // 當(dāng)前數(shù)   >  劃分值
            swap(arr, --more, index);
        } else {
            index++;
        }
    }
    swap(arr, more, R);
    return new int[] { less + 1, more };
}

023快速排序時(shí)間復(fù)雜度?

快速排序的時(shí)間復(fù)雜度在最壞情況下是O(N2),平均的時(shí)間復(fù)雜度是O(N*lgN)。
假設(shè)被排序的數(shù)列中有N個(gè)數(shù)。遍歷一次的時(shí)間復(fù)雜度是O(N),需要遍歷多少次呢? 至少lg(N+1)次,最多N次。 為什么最少是lg(N+1)次? 快速排序是采用的分治法進(jìn)行遍歷的,我們將它看作一棵二叉樹,它需要遍歷的次數(shù)就是二叉樹的深度,而根據(jù)完全二叉樹的定義,它的深度至少是lg(N+1)。因此,快速排序的遍歷次數(shù)最少是lg(N+1)次。 為什么最多是N次? 這個(gè)應(yīng)該非常簡(jiǎn)單,還是將快速排序看作一棵二叉樹,它的深度最大是N。因此,快讀排序的遍歷次數(shù)最多是N次。

024快速排序穩(wěn)定性?

快速排序是不穩(wěn)定的算法,它不滿足穩(wěn)定算法的定義。

025什么是堆排序?

堆結(jié)構(gòu)如下圖,堆的實(shí)際結(jié)構(gòu)是數(shù)組,但是我們?cè)诜治鏊臅r(shí)候用的是有特殊標(biāo)準(zhǔn)的完全二叉樹來(lái)分析。也就是說數(shù)組是堆的實(shí)際物理結(jié)構(gòu)而完全二叉樹是我們便于分析的邏輯結(jié)構(gòu)。堆有兩種:大根堆和小根堆。每個(gè)節(jié)點(diǎn)的值都大于其左孩子和右孩子節(jié)點(diǎn)的值,稱為大根堆。每個(gè)節(jié)點(diǎn)的值都小于其左孩子和右孩子節(jié)點(diǎn)的值,稱為小根堆。

上面的結(jié)構(gòu)映射成數(shù)組就變成了下面這個(gè)樣子

026堆排序的特點(diǎn)?

1.首先堆的大小是提前知道的,根節(jié)點(diǎn)的位置上存儲(chǔ)的數(shù)據(jù)總是在數(shù)組的第一個(gè)元素。

2.假設(shè)一個(gè)非根節(jié)點(diǎn)所存儲(chǔ)的數(shù)據(jù)的索引為i,那么它的父節(jié)點(diǎn)存儲(chǔ)的數(shù)據(jù)所對(duì)應(yīng)的索引就為[(i-1)/2]

3.假設(shè)一個(gè)節(jié)點(diǎn)所存儲(chǔ)的數(shù)據(jù)的索引為i,那么它的孩子(如果有)所存儲(chǔ)的數(shù)據(jù)分別所對(duì)應(yīng)的索引為:左孩子是[2*i+1],右孩子是[2*i+2]

027堆排序的流程?

第一步,將待排序的數(shù)組構(gòu)造成一個(gè)大根堆,假設(shè)有下面這個(gè)數(shù)組:

具體思路:第一次保證0~0位置大根堆結(jié)構(gòu),第二次保證0~1位置大根堆結(jié)構(gòu),第三次保證0~2位置大根堆結(jié)構(gòu)...直到保證0~n-1位置大根堆結(jié)構(gòu)(每次新插入的數(shù)據(jù)都與其父節(jié)點(diǎn)進(jìn)行比較,如果插入的數(shù)比父節(jié)點(diǎn)大,則與父節(jié)點(diǎn)交換。周而復(fù)始一直向上比較,直到小于等于父節(jié)點(diǎn)或者來(lái)到了根節(jié)點(diǎn)則終止)

【1】插入6的時(shí)候,6大于他的父節(jié)點(diǎn)3,即arr(1)>arr(0),則交換;此時(shí)保證了0~1位置是大根堆結(jié)構(gòu),如下圖:

【2】插入8的時(shí)候,8大于其父節(jié)點(diǎn)6,即arr(2)>arr(0),則交換;此時(shí),保證了0~2位置是大根堆結(jié)構(gòu),如下圖

【3】插入5的時(shí)候,5大于其父節(jié)點(diǎn)3,則交換,交換之后,5又發(fā)現(xiàn)比8小,所以不交換;此時(shí),保證了0~3位置大根堆結(jié)構(gòu),如下圖

【4】插入7的時(shí)候,7大于其父節(jié)點(diǎn)5,則交換,交換之后,7又發(fā)現(xiàn)比8小,所以不交換;此時(shí)整個(gè)數(shù)組已經(jīng)是大根堆結(jié)構(gòu)

第二步,將根節(jié)點(diǎn)的數(shù)與末尾的數(shù)交換

【1】大根堆中整個(gè)數(shù)組的最大值就是堆結(jié)構(gòu)的父節(jié)點(diǎn),接下來(lái)將根節(jié)點(diǎn)的數(shù)8與末尾的數(shù)5交換

第三步,將剩余的n-1個(gè)數(shù)再構(gòu)造成大根堆

如上圖所示,此時(shí)最大數(shù)8已經(jīng)來(lái)到末尾,讓堆的有效大小減1,后面拿頂端的數(shù)與其左右孩子較大的數(shù)進(jìn)行比較,如果頂端的數(shù)大于其左右孩子較大的數(shù),則停止,如果頂端的數(shù)小于其左右孩子較大的數(shù),則交換;周而復(fù)始一直向下比較,直到大于左右孩子較大的數(shù)或者沒有孩子節(jié)點(diǎn)則終止。

下圖中,5的左右孩子中,左孩子7比右孩子6大,則5與7進(jìn)行比較,發(fā)現(xiàn)5<7,則交換;交換后,發(fā)現(xiàn)5已經(jīng)大于他的左孩子,說明剩余的數(shù)已經(jīng)構(gòu)成大根堆,

第四步,再將第二步和第三步反復(fù)執(zhí)行,便能得到有序數(shù)組

028如何將待排序的數(shù)組構(gòu)造成一個(gè)大根堆?

首先遍歷該數(shù)組,假設(shè)某個(gè)數(shù)處于index位置,每次都讓index位置和父節(jié)點(diǎn)位置的數(shù)進(jìn)行比較,如果大于父節(jié)點(diǎn)的值就交換位置,....周而復(fù)始,一直到不能往上為止。

for (int i = 0; i < arr.length; i++) { // O(N)
    while (arr[index] > arr[(index - 1) / 2]) {
        swap(arr, index, (index - 1) / 2);
        index = (index - 1) / 2;
    }	
}

029如何將剩余的n-1個(gè)數(shù)再構(gòu)造成大根堆?

先將大根堆的頭節(jié)點(diǎn)的數(shù)據(jù)與堆上的最后一個(gè)數(shù)交換位置后,把堆有效區(qū)的長(zhǎng)度減1,再?gòu)念^節(jié)點(diǎn)開始做向下的比較,每次都和左右孩子中較大值進(jìn)行比較,如果父節(jié)點(diǎn)比最大孩子的值下就交換位置....周而復(fù)始,一直到不能往下為止。

// 某個(gè)數(shù)在index位置,能否往下移動(dòng)
public static void heapify(int[] arr, int index, int heapSize) {
    int left = index * 2 + 1; // 左孩子的下標(biāo)
    while (left < heapSize) { // 下方還有孩子的時(shí)候
        // 兩個(gè)孩子中,誰(shuí)的值大,把下標(biāo)給largest		
        int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
        // 父和較大的孩子之間,誰(shuí)的值大,把下標(biāo)給largest
        largest = arr[largest] > arr[index] ? largest : index;
        if (largest == index) {
            break;	
        }
        swap(arr, largest, index);
        index = largest;
        left = index * 2 + 1;
    }
}

030堆的排序如何實(shí)現(xiàn)?

具體實(shí)現(xiàn)前面的問題,具體源代碼實(shí)現(xiàn)如下:

public static void heapSort(int[] arr) {
    if (arr == null || arr.length < 2) {
        return;
    }
    //第一步,將待排序的數(shù)組構(gòu)造成一個(gè)大根堆
    for (int i = 0; i < arr.length; i++) { // O(N)
        heapInsert(arr, i); // O(logN)
    }
    int heapSize = arr.length;
    //第二步,將根節(jié)點(diǎn)的數(shù)與末尾的數(shù)交換
    swap(arr, 0, --heapSize);
    while (heapSize > 0) { // O(N)
        //第三步,將剩余的n-1個(gè)數(shù)再構(gòu)造成大根堆
        heapify(arr, 0, heapSize); // O(logN)
        //第二步,將根節(jié)點(diǎn)的數(shù)與末尾的數(shù)交換
        swap(arr, 0, --heapSize); // O(1)
    }
}

031什么是桶排序?

1)桶排序(Bucket sort)或所謂的箱排序,是一個(gè)排序算法,工作的原理是將數(shù)組分到有限數(shù)量的桶里。每個(gè)桶再個(gè)別排序(有可能再使用別的排序算法或是以遞歸方式繼續(xù)使用桶排序進(jìn)行排序),最后依次把各個(gè)桶中的記錄列出來(lái)記得到有序序列。桶排序是鴿巢排序的一種歸納結(jié)果。當(dāng)要被排序的數(shù)組內(nèi)的數(shù)值是均勻分配的時(shí)候,桶排序使用線性時(shí)間(Θ(n))。但桶排序并不是比較排序,他不受到O(n log n)下限的影響。

2)算法圖解

032堆排序平均執(zhí)行的時(shí)間復(fù)雜度和需要附加的存儲(chǔ)空間復(fù)雜度分別是( )

A. O(n^2)和O(1)
B. O(nlog(n))和O(1)
C. O(nlog(n))和O(n)
D. O(n^2)和O(n)
答案:B
解析:暫無(wú)解析

033什么是計(jì)數(shù)排序?

1)計(jì)數(shù)排序不是一個(gè)基于比較的排序算法。它是用一個(gè)數(shù)組來(lái)統(tǒng)計(jì)每種數(shù)字出現(xiàn)的次數(shù),然后按照大小順序?qū)⑵湟来畏呕卦瓟?shù)組。但是計(jì)數(shù)排序有一個(gè)很嚴(yán)重的問題,就是其只能對(duì)整數(shù)進(jìn)行排序,一旦遇到字符串時(shí),就無(wú)能為力了。

2 )算法圖解

第一步:找出原始數(shù)組【0,2,5,3,7,9,10,3,7,6】中元素值最大的,記為max=10。

第二步:創(chuàng)建一個(gè)計(jì)數(shù)數(shù)組count,數(shù)組長(zhǎng)度是max值加1,其元素默認(rèn)值都為0。

第三步:遍歷原始數(shù)組中的元素,以原始數(shù)組中的元素作為計(jì)數(shù)數(shù)組count的索引,以原始數(shù)組中的元素出現(xiàn)次數(shù)作為計(jì)數(shù)數(shù)組count的元素值。下圖可以得到原始數(shù)組【0,2,5,3,7,9,10,3,7,6】中元素0出現(xiàn)1次,元素2出現(xiàn)1次,元素3出現(xiàn)2次,元素5出現(xiàn)1次,元素6出現(xiàn)1次,元素7出現(xiàn)2次,元素9出現(xiàn)1次,元素10出現(xiàn)1次。

第四步:遍歷計(jì)數(shù)數(shù)組count,找出其中元素值大于0的元素,將其對(duì)應(yīng)的索引作為元素值填充到結(jié)果數(shù)組result中去,每處理一次,計(jì)數(shù)數(shù)組count中的該元素值減1,直到該元素值不大于0,依次處理計(jì)數(shù)數(shù)組count中剩下的元素。

034計(jì)數(shù)排序的代碼實(shí)現(xiàn)?

public static void countSort(int[] arr) {
    if (arr == null || arr.length < 2) {
        return;
    }
    int max = Integer.MIN_VALUE;
    for (int i = 0; i < arr.length; i++) {
        max = Math.max(max, arr[i]);
    }
    int[] bucket = new int[max + 1];
    for (int i = 0; i < arr.length; i++) {
        bucket[arr[i]]++;
    }
    int i = 0;
    for (int j = 0; j < bucket.length; j++) {
        while (bucket[j]-- > 0) {
            arr[i++] = j;
        }
    }
}    

035桶排序的代碼實(shí)現(xiàn)?

public static void bucketSort(int[] arr){
    // 計(jì)算最大值與最小值
    int max = Integer.MIN_VALUE;
    int min = Integer.MAX_VALUE;
    for(int i = 0; i < arr.length; i++){
        max = Math.max(max, arr[i]);
        min = Math.min(min, arr[i]);
    }
    // 計(jì)算桶的數(shù)量
    int bucketNum = (max - min) / arr.length + 1;
    ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
    for(int i = 0; i < bucketNum; i++){
        bucketArr.add(new ArrayList<Integer>());
    }
    // 將每個(gè)元素放入桶
    for(int i = 0; i < arr.length; i++){
        int num = (arr[i] - min) / (arr.length);
        bucketArr.get(num).add(arr[i]);
    }
    // 對(duì)每個(gè)桶進(jìn)行排序
    for(int i = 0; i < bucketArr.size(); i++){
        Collections.sort(bucketArr.get(i));
    }
    // 將桶中的元素賦值到原序列
    int index = 0;
    for(int i = 0; i < bucketArr.size(); i++){
        for(int j = 0; j < bucketArr.get(i).size(); j++){
            arr[index++] = bucketArr.get(i).get(j);
        }
    } 
}

036什么是基數(shù)排序?

1)基數(shù)排序是對(duì)桶排序的一種改進(jìn),這種改進(jìn)是讓“桶排序”適合于更大的元素值集合的情況,而不是提高性能。它的基本思想是:將整數(shù)按位數(shù)切割成不同的數(shù)字,然后按每個(gè)位數(shù)分別比較。

2)算法圖解

第一步,將所有待比較數(shù)值根據(jù)個(gè)位數(shù)的數(shù)值分別分配至編號(hào)0到9的桶中;

第二步,桶中數(shù)據(jù)根據(jù)先進(jìn)先出的原則出來(lái),收集完整的序列;

第三步,十位、百位....周而復(fù)始

037基數(shù)排序的代碼實(shí)現(xiàn)?

//digit代表最大的數(shù)有幾個(gè)十進(jìn)制位
public static void radixSort(int[] arr, int L, int R, int digit) {
    //十進(jìn)制數(shù)
    final int radix = 10;
    int i = 0, j = 0;
    // 有多少個(gè)數(shù)準(zhǔn)備多少個(gè)輔助空間
    int[] bucket = new int[R - L + 1];
    for (int d = 1; d <= digit; d++) { // 有多少位就循環(huán)幾次
        //十進(jìn)制的數(shù),創(chuàng)建長(zhǎng)度為10的數(shù)組
        int[] count = new int[radix]; // count[0..9]
        for (i = L; i <= R; i++) {
            j = getDigit(arr[i], d);//獲取該數(shù)的個(gè)位、十位、百位......上的數(shù)
            count[j]++;//獲取數(shù)組中每個(gè)數(shù)每位分別是1、2、3....9數(shù)分別總共有幾個(gè)
        }
        for (i = 1; i < radix; i++) {
            //獲取數(shù)組中每個(gè)數(shù)每位分別是<=1、<=2、<=3....<=9數(shù)分別總共有幾個(gè)
            count[i] = count[i] + count[i - 1];
        }
        for (i = R; i >= L; i--) {
            j = getDigit(arr[i], d);//獲取該數(shù)的個(gè)位、十位、百位......上的數(shù)
            bucket[count[j] - 1] = arr[i];//將數(shù)放回到輔助空間
            count[j]--;
        }
        for (i = L, j = 0; i <= R; i++, j++) {
            arr[i] = bucket[j];
        }
    }
}
//獲取該數(shù)的個(gè)位、十位、百位......上的數(shù)	
public static int getDigit(int x, int d) {		
    return ((x / ((int) Math.pow(10, d - 1))) % 10);
}

038什么是時(shí)間復(fù)雜度?

時(shí)間復(fù)雜度指執(zhí)行這個(gè)算法需要消耗多少時(shí)間,也可以認(rèn)為是對(duì)排序數(shù)據(jù)的總的操作次數(shù)。常見的時(shí)間復(fù)雜度有:常數(shù)階O(1),對(duì)數(shù)階O(log2n),線性階O(n), 線性對(duì)數(shù)階O(nlog2n),平方階O(n2)。

//時(shí)間復(fù)雜度O(1)
sum = n*(n+1)/2; 
//時(shí)間復(fù)雜度O(n)
for(int?i = 0; i < n; i++){ 
    System.out.println("%d ",i);
} 
//時(shí)間復(fù)雜度O(n^2)
for(int?i = 0; i < n; i++){ 
    for(int?j = 0; j < n; j++){ 
        System.out.println("%d ",i); 
    }
} 
//運(yùn)行次數(shù)為(1+n)*n/2//時(shí)間復(fù)雜度O(n^2)
for(int?i = 0; i < n; i++){ 
    for(int?j = i; j < n; j++){ 
        System.out.println("%d ",i); 
    }
} 
//設(shè)執(zhí)行次數(shù)為x. 2^x = n 即x = log2n,時(shí)間復(fù)雜度O(log2n)
int?i = 1, n = 100;
while(i < n){ 
    i = i * 2;
}

039常見的時(shí)間復(fù)雜度排序?

O(1)< O(logn)<O(n)<O(nlog2n)<O(n2)<O(n3)<…<O(2n)<O(n!)

040空間復(fù)雜度是什么?

空間復(fù)雜度是指算法在計(jì)算機(jī)內(nèi)執(zhí)行時(shí)所需存儲(chǔ)空間的度量,它也是問題規(guī)模n的函數(shù)

常見的空間復(fù)雜度有:常量空間復(fù)雜度O(1)、對(duì)數(shù)空間復(fù)雜度O(log2N)、線性空間復(fù)雜度O(n)。

041時(shí)間復(fù)雜度和空間復(fù)雜度關(guān)系?

對(duì)于一個(gè)算法來(lái)說,空間復(fù)雜度和時(shí)間復(fù)雜度往往是相互影響的。當(dāng)追求一個(gè)較好的時(shí)間復(fù)雜度時(shí),可能會(huì)使空間復(fù)雜度的性能變差,即可能導(dǎo)致占用較多的存儲(chǔ)空間;反之,當(dāng)追求一個(gè)較好的空間復(fù)雜度時(shí),可能會(huì)使時(shí)間復(fù)雜度的性能變差,即可能導(dǎo)致占用較長(zhǎng)的運(yùn)行時(shí)間。有時(shí)我們可以用空間來(lái)?yè)Q取時(shí)間以達(dá)到目的。

042什么是算法穩(wěn)定性?

假定在待排序的記錄序列中,存在多個(gè)具有相同的關(guān)鍵字的記錄,若經(jīng)過排序,這些記錄的相對(duì)次序保持不變,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,則稱這種排序算法是穩(wěn)定的;否則稱為不穩(wěn)定的。排序算法是否為穩(wěn)定的是由算法具體實(shí)現(xiàn)決定的。總體上,堆排序、快速排序、希爾排序、直接選擇排序不是穩(wěn)定的排序算法,而冒泡排序、直接插入排序、歸并排序、基數(shù)排序、計(jì)數(shù)排序、桶排序是穩(wěn)定的排序算法。

043比較排序和非比較排序的區(qū)別?

比較類排序:通過比較來(lái)決定元素間的相對(duì)次序,由于其時(shí)間復(fù)雜度不能突破O(nlogn),因此也稱為非線性時(shí)間比較類排序。如冒泡排序、選擇排序、插入排序、歸并排序、堆排序、快速排序

非比較類排序:不通過比較來(lái)決定元素間的相對(duì)次序,它可以突破基于比較排序的時(shí)間下界,以線性時(shí)間運(yùn)行,因此也稱為線性時(shí)間非比較類排序。 如計(jì)數(shù)排序、基數(shù)排序、桶排序

044十大排序的復(fù)雜度及穩(wěn)定性?

045下列哪種排序算法不是穩(wěn)定的?

A. 基數(shù)排序
B. 冒泡排序
C. 選擇排序
D. 歸并排序
答案:C
解析:選擇排序是不穩(wěn)定的,如{2*,2,1},第一次遍歷將2*與1互換,結(jié)果為{1,2,2*},2與2*位置互換
其余排序均是穩(wěn)定的

046在各自最優(yōu)條件下,對(duì)N個(gè)數(shù)進(jìn)行排序,哪個(gè)算法復(fù)雜度最低的是? ()

A. 插入排序
B. 快速排序
C. 堆排序
D. 歸并排序
答案:A
解析:插入排序:最佳O(N)
         快速排序:最佳O(NlogN)
         堆    排序:最佳O(NlogN)
         歸并排序:最佳O(NlogN),因此選擇插入排序。

目錄

001什么是冒泡排序? 002冒泡排序的代碼實(shí)現(xiàn)? 003冒泡排序時(shí)間復(fù)雜度? 004冒泡排序穩(wěn)定性? 005冒泡排序的改進(jìn)版實(shí)現(xiàn)。 006什么是選擇排序? 007選擇排序的代碼實(shí)現(xiàn)? 008有一組數(shù)據(jù)“12,15,1,18,2,35,30,11”,用選擇法由小到大排序,第2趟交換數(shù)據(jù)后數(shù)據(jù)的順序是( )。 009在選擇排序中,以下什么情況下選擇排序會(huì)更快執(zhí)行? 010什么是插入排序? 011插入排序的代碼實(shí)現(xiàn)? 012設(shè)一組初始記錄關(guān)鍵字的長(zhǎng)度為8,則最多經(jīng)過( )趟插入排序可以得到有序序列。 013什么是希爾排序? 014希爾排序的代碼實(shí)現(xiàn)? 015希爾排序的組內(nèi)排序采用的是( )。 016設(shè) 一組初始記錄關(guān)鍵字序列為(50,40,95,20,15,70,60,45),則以增量d=4的一趟希爾排序結(jié)束后前4條記錄關(guān)鍵字為( )。 017什么是歸并排序? 018歸并排序的代碼實(shí)現(xiàn)? 019關(guān)于歸并排序敘述正確的是( ). 020若外部存儲(chǔ)上有3110400個(gè)記錄,做6路平衡歸并排序,計(jì)算機(jī)內(nèi)存工作區(qū)能容納400個(gè)記錄,則排序好所有記錄,需要作幾趟歸并排序( ) 021什么是快速排序? 022快速排序的代碼實(shí)現(xiàn)? 023快速排序時(shí)間復(fù)雜度? 024快速排序穩(wěn)定性? 025什么是堆排序? 026堆排序的特點(diǎn)? 027堆排序的流程? 028如何將待排序的數(shù)組構(gòu)造成一個(gè)大根堆? 029如何將剩余的n-1個(gè)數(shù)再構(gòu)造成大根堆? 030堆的排序如何實(shí)現(xiàn)? 031什么是桶排序? 032堆排序平均執(zhí)行的時(shí)間復(fù)雜度和需要附加的存儲(chǔ)空間復(fù)雜度分別是( ) 033什么是計(jì)數(shù)排序? 034計(jì)數(shù)排序的代碼實(shí)現(xiàn)? 035桶排序的代碼實(shí)現(xiàn)? 036什么是基數(shù)排序? 037基數(shù)排序的代碼實(shí)現(xiàn)? 038什么是時(shí)間復(fù)雜度? 039常見的時(shí)間復(fù)雜度排序? 040空間復(fù)雜度是什么? 041時(shí)間復(fù)雜度和空間復(fù)雜度關(guān)系? 042什么是算法穩(wěn)定性? 043比較排序和非比較排序的區(qū)別? 044十大排序的復(fù)雜度及穩(wěn)定性? 045下列哪種排序算法不是穩(wěn)定的? 046在各自最優(yōu)條件下,對(duì)N個(gè)數(shù)進(jìn)行排序,哪個(gè)算法復(fù)雜度最低的是? ()
返回頂部
主站蜘蛛池模板: 亚洲十八精品网站 | 国产在线h视频 | 青青青国产在线手机免费观看 | 欧美亚洲国产精品久久第一页 | 夜夜偷天天爽夜夜爱 | 美女伊人 | 最近中文字幕大全高清视频 | 亚洲欧美乱综合图片区小说区 | 亚洲综合天堂网 | 日本国产在线视频 | 成人a网站 | 一级a毛片免费观看久久精品 | 久久国产首页 | 亚洲欧美日韩中文高清一 | 中文字幕成人免费视频 | 国产精品视频无圣光一区 | 成人涩涩网站 | 国产制服在线 | 日本一区二区视频在线 | 天堂免费在线视频 | 免费观看黄色一级片 | 欧美xxxx色视频在线观看免费 | free亚洲| 最近中文字幕高清字幕 | 在线成人看片 | 成人在线免费视频播放 | 欧美freesex呦交6_10 | 老司机深夜影院入口aaaa | 日韩欧美精品在线视频 | 国产亚洲一区二区三区不卡 | 又黄又爽又色的视频 | 亚洲精品动漫在线 | 一 级 黄 色 片生活片 | 黄色一级免费看 | 成人午夜在线视频 | 人成午夜性刺激免费 | 黄网站色视频免费观看 | 日韩第3页 | 漂流教室在线观看 | 日本中文字幕在线观看视频 | 亚洲精品中文字幕久久久久久 |