三個排序演算法
1. vb三種基本排序演算法
三種基本排序演算法(與哪種編程語言無關):
冒泡排序演算法、選擇排序演算法、插入排序演算法
2. 一文詳解三種時間復雜度為O(N)的排序演算法
導讀數據結構和演算法這個東西,如果你不去學,可能真的這輩子都用不到,也感受不到它的好。但是一旦掌握,你就會常常被它的強大威力所折服。之前你可能需要費很大勁兒來優化的代碼,需要花很多心思來設計的架構,用了數據結構和演算法之後,很容易就可以解決了。
排序是一個非常經典的問題,它以一定的順序對一個數組(或一個列表)中的項進行重新排序(可以進行比較的,例如整數,浮點數,字元串等)。
有許多不同的排序演算法,每個都有其自身的優點和局限性。
基於比較的排序演算法:
比較數組的元素,並決定是否交換它們的位置。
BUB-冒泡排序
SEL-選擇排序
INS-插入排序
MER-歸並排序(遞歸實現)
QUI-快速排序(遞歸實現)
R-Q-隨機快速排序(遞歸實現)
不基於比較的排序演算法:
COU-計數排序
RAD-基數排序
我們來逐一破解這些排序演算法。
本文分析冒泡排序、選擇排序和插入排序。
一、冒泡排序假設數組arr長度為$N$,冒泡排序的過程為:
在arr[0~N-1]范圍上:
arr[0]和arr[1],誰大誰來到1位置;
arr[1]和arr[2],誰大誰來到2位置;
[N-2]和arr[N-1],誰大誰來到N-1位置;
在arr[0~N-2]范圍上,重復上面的過程,但最後一步是arr[N-3]和arr[N-2],誰大誰來到N-2位置;
在arr[0~N-3]范圍上,重復上面的過程,但最後一步是arr[N-4]和arr[N-3],誰大誰來到N-3位置;
…
最後在arr[0~1]范圍上,重復上面的過程,但最後一步是arr[0]和arr[1],誰大誰來到1位置。
整個過程將最大的元素移動到最右側,也就是最大的元素浮動到最右邊,像冒泡一樣。
如圖所示:
如圖展示了第1趟排序的過程。
自己會動的才是好圖:
代碼實現:
publicclassBubbleSort{publicstaticvoidmain(String[]args){int[]arr={18,15,13,17,6,20,15,9};sort(arr);}publicstaticvoidsort(int[]arr){if(arr==null||arr.length<2){return;}//想要讓0~i位置上有序,i一開始在數組的最大索引位置上,每比完1次,減1for(inti=arr.length-1;i>0;i--){//0~i//0~(i-1)//0~(i-2)...//0~1for(intj=0;j<i;j++){if(arr[j]>arr[j+1]){inttemp=arr[j];arr[j]=arr[j+1];arr[j+1]=temp;}}System.out.println("0~"+i+"位置比較結果:"+Arrays.toString(arr));}}}執行結果:
第0趟比較結果:[15,13,17,6,18,15,9,20]第1趟比較結果:[13,15,6,17,15,9,18,20]第2趟比較結果:[13,6,15,15,9,17,18,20]第3趟比較結果:[6,13,15,9,15,17,18,20]第4趟比較結果:[6,13,9,15,15,17,18,20]第5趟比較結果:[6,9,13,15,15,17,18,20]第6趟比較結果:[6,9,13,15,15,17,18,20]第7趟比較結果:[6,9,13,15,15,17,18,20]時間復雜度的計算:
比較和交換需要一個以常量為界的時間,我們稱之為$c$。
BubbleSort中有兩個嵌套循環。
外循環正好運行$N$次迭代。但內部循環運行變得越來越短:
當i=0,(N-1)次迭代(比較和可能交換)時。
當i=1,(N-2)次迭代時,...
當i=(N-2)時,1次迭代,
當i=(N-1),0迭代.
因此:
$$總迭代次數=(N-1)+(N-2)+...+1+0=N×(N-1)/2$$
計算總時間:$$總時間=c×N×(N-1)/2=O(N?)$$
二、選擇排序給定$N$個元素和L=0的數組,選擇排序過程為:
在[L...N-1]范圍內找出最小項X的位置,
用第L項交換X,
將下限L增加1並重復步驟1直到L=N-2。
手繪選擇排序過程:
動畫演示:
代碼實現:
publicclassSelectionSort{publicstaticvoidmain(String[]args){int[]arr={18,15,13,17,6,20,15,9};sort(arr);}publicstaticvoidsort(int[]arr){for(inti=0;i<arr.length-1;i++){//目的:找到最小值的位置,並將該位置的數與i位置的數交換intminIndex=i;for(intj=i+1;j<arr.length;j++){minIndex=arr[j]>arr[minIndex]?minIndex:j;}//找到最小值後,與i位置的數交換inttemp=arr[i];arr[i]=arr[minIndex];arr[minIndex]=temp;System.out.println("第"+i+"~"+(arr.length-1)+"位置上的最小值索引為"+minIndex+",最小值為:"+arr[minIndex]+",本次排序結果:"+Arrays.toString(arr));}}}運行結果:
第0~7位置上的最小值索引為4,最小值為:18,本次排序結果:[6,15,13,17,18,20,15,9]第1~7位置上的最小值索引為7,最小值為:15,本次排序結果:[6,9,13,17,18,20,15,15]第2~7位置上的最小值索引為2,最小值為:13,本次排序結果:[6,9,13,17,18,20,15,15]第3~7位置上的最小值索引為7,最小值為:17,本次排序結果:[6,9,13,15,18,20,15,17]第4~7位置上的最小值索引為6,最小值為:18,本次排序結果:[6,9,13,15,15,20,18,17]第5~7位置上的最小值索引為7,最小值為:20,本次排序結果:[6,9,13,15,15,17,18,20]第6~7位置上的最小值索引為6,最小值為:18,本次排序結果:[6,9,13,15,15,17,18,20]總結一下選擇排序的過程:
arr[0~N-1]范圍上,找到最小值所在的位置,然後把最小值交換到0位置。
arr[1~N-1]范圍上,找到最小值所在的位置,然後把最小值交換到1位置。
arr[2~N-1]范圍上,找到最小值所在的位置,然後把最小值交換到2位置。
…
arr[N-1~N-1]范圍上,找到最小值位置,然後把最小值交換到N-1位置。
估算:很明顯,如果arr長度為N,每一步常數操作的數量,如等差數列一般,所以有:
$$總的常數操作數量=a(N?)+bN+c(a、b、c都是常數)$$
所以選擇排序的時間復雜度為$O(N?)$。
三、插入排序這個演算法比較好理解,想像一下平時打撲克牌,我們很自然的就會把一張牌和手裡的牌挨個比較一下,並把它插入到合適的位置。
過程:
想讓arr[0~0]上有序,這個范圍只有一個數,當然是有序的;
想讓arr[0~1]上有序,所以從arr[1]開始往前看,如果arr[1]<arr[0],就交換。否則什麼也不做;
…
想讓arr[0~i]上有序,所以從arr[i]開始往前看,arr[i]這個數不停向左移動,一直移動到左邊的數字不再比自己大,停止移動;
最後一步,想讓arr[0~N-1]上有序,arr[N-1]這個數不停向左移動,一直移動到左邊的數字不再比自己大,停止移動。
估算時發現這個演算法流程的復雜程度,會因為數據狀況的不同而不同。
如果某個演算法流程的復雜程度會根據數據狀況的不同而不同,那麼必須要按照最差情況來估計。
很明顯,在最差情況下,如果arr長度為N,插入排序的每一步常數操作的數量,還是如等差數列一般。
所以有:
$$總的常數操作數量=a(N?)+bN+c(a、b、c都是常數)$$
因此插入排序排序的時間復雜度為$O(N?)$。
代碼實現:
publicclassInsertionSort{publicstaticvoidmain(String[]args){int[]arr={18,15,13,17,6,20,15,9};sort(arr);}publicstaticvoidsort(int[]arr){if(arr==null||arr.length<2){return;}//想讓0~i位置上有序,從i位置往前看,一直到左邊的數不比自己大了,停止往左看for(inti=1;i<arr.length;i++){//j=i表示從i位置開始,j--表示往前看for(intj=i;j>0;j--){if(arr[j]<arr[j-1]){inttemp=arr[j-1];arr[j-1]=arr[j];arr[j]=temp;}}System.out.println("從"+i+"位置往前看,直到左邊的數不比自己大,本次結果:"+Arrays.toString(arr));}}}運行結果:
從1位置往前看,直到左邊的數不比自己大,本次結果:[15,18,13,17,6,20,15,9]從2位置往前看,直到左邊的數不比自己大,本次結果:[13,15,18,17,6,20,15,9]從3位置往前看,直到左邊的數不比自己大,本次結果:[13,15,17,18,6,20,15,9]從4位置往前看,直到左邊的數不比自己大,本次結果:[6,13,15,17,18,20,15,9]從5位置往前看,直到左邊的數不比自己大,本次結果:[6,13,15,17,18,20,15,9]從6位置往前看,直到左邊的數不比自己大,本次結果:[6,13,15,15,17,18,20,9]從7位置往前看,直到左邊的數不比自己大,本次結果:[6,9,13,15,15,17,18,20]原文:juejin.cn/post/7128721614144798750
3. python常見的三種列表排序演算法分別是什麼
排序是計算機程序設計中的一種重要操作,它的功能是將一個數據元素的任意序列,重新排列成一個關鍵字有序的序列。那麼python列表排序演算法有哪些?本文主要為大家講述python中禪棚經常用的三種排序演算法:冒泡排序、插入排序和選擇排序。
1、冒泡排序
冒泡排序,Bubble
Sort,是一種簡單的排序演算法。它重復地遍歷要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。遍歷數列的工作是重復地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個演算法的名字由來是因為越小的元素會經由交換慢慢浮到數列的頂端。
2、插入排序
插戚襲差入排序,Insertion
Sort,是一種簡單直觀的排序演算法。它的工作原理是通過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應位置並插入。插入排序在實現上,在從後向前的掃描過程中,需要把已排序元素逐步向後挪位,為最新元素提供插入空間。
3、選擇高皮排序
選擇排序,Selection
Sort,是一種簡單直觀的排序演算法。它的工作原理如下:首先在未排序序列中找到最小、最大元素,存放到排序序列的起始位置,然後再從剩餘未排序元素中繼續尋找最小、最大元素。放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。
4. python常見的三種列表排序演算法分別是什麼
python中有兩種排序方法,list內置sort()方法或者python內置的全局sorted()方法二者區別為:sort()方法對list排序會修改list本身,不會返回新list。sort()只能對list進行排序。sorted()方法會返回新的list,保留原來的list。
先說reverse,這個很簡單,就是指出是否進行倒序排序:一般情況下,1排在2的前面,而倒序則相反。key參數:一般它是一個函數,它接受列表中每一個元素,返回一個可用用於比較的值。
在Python中,Python演算法有:插入排序、希爾排序、選擇排序、冒泡排序、歸並排序、快速排序、堆排序、基數排序等。冒泡排序冒泡排序也是一種簡單直觀的排序演算法。
③對所有兩個小數列重復第二步,直至各區間只有一個數。排序演示演算法實現希爾排序介紹希爾排序(ShellSort)是插入排序的一種,也是縮小增量排序,是直接插入排序演算法的一種更高效的改進版本。
排序演算法是《數據結構與演算法》中最基本的演算法之一。排序演算法可以分為內部排序和外部排序,內部排序是數據記錄在內存中進行排序,而外部排序是因排序的數據很大,一次不能容納全部的排序記錄,在排序過程中需要訪問外存。