<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【算法】動圖展示八大常用排序算法,一次看個夠!

          共 833字,需瀏覽 2分鐘

           ·

          2021-12-09 15:38

          本文介紹常見的八大排序算法:直接插入排序、希爾排序、選擇排序、堆排序、冒泡排序、快排、歸并排序以及計數(shù)排序

          文章內容很干,也很長,不過有多種動圖圖解,希望可以給枯燥的算法學習帶來一抹亮色!

          如果對于復雜度還不清楚,可以查看下面的文章

          五分鐘復雜度

          1冒泡排序

          對于冒泡排序相信我們都比較熟悉了,其核心思想就是相鄰元素兩兩比較,把較大的元素放到后面,在一輪比較完成之后,最大的元素就位于最后一個位置了,就好像是氣泡,慢慢的浮出了水面一樣


          Java 版實現(xiàn)

          public?class?BubbleSort1?{
          ????public?static?void?BubbleSort(int[]?arr)?{
          ????????boolean?flag?=?true;
          ????????while(flag){
          ????????????int?temp;//定義一個臨時變量
          ????????????for(int?i=0;i1;i++){//冒泡趟數(shù),n-1趟
          ????????????????for(int?j=0;j1;j++){
          ????????????????????if(arr[j+1]????????????????????????temp?=?arr[j];
          ????????????????????????arr[j]?=?arr[j+1];
          ????????????????????????arr[j+1]?=?temp;
          ????????????????????????flag?=?true;
          ????????????????????}
          ????????????????}
          ????????????????if(!flag){
          ????????????????????break;//若果沒有發(fā)生交換,則退出循環(huán)
          ????????????????}
          ????????????}
          ????????}
          ????}
          ????public?static?void?main(String[]?args)?{
          ????????int?arr[]?=?new?int[]{1,6,2,2,5};
          ????????BubbleSort.BubbleSort(arr);
          ????????System.out.println(Arrays.toString(arr));
          ????}
          }

          Python 版實現(xiàn)

          def?bubble_sort(data,?reverse=False):
          ????"""
          ????:param?data:?list?type?data
          ????:param?reverse:
          ????:return:?list?type?data
          ????"""

          ????if?not?reverse:
          ????????for?i?in?range(len(data)?-?1):
          ????????????for?j?in?range(len(data)?-?1?-i):
          ????????????????if?data[j]?>?data[j+1]:
          ????????????????????data[j],?data[j+1]?=?data[j+1],?data[j]
          ????????return?data
          ????else:
          ????????for?i?in?range(len(data)?-?1):
          ????????????for?j?in?range(len(data)?-?1?-i):
          ????????????????if?data[j]?1]:
          ????????????????????data[j],?data[j?+?1]?=?data[j?+?1],?data[j]
          ????????return?data

          冒泡排序算法還是比較好理解的,只需要進行兩次循環(huán),最外層的循環(huán)代表排序元素的個數(shù),內部循環(huán)則進行兩兩比較,時間復雜度為 O(n^2)

          2快速排序

          快排的思想為首先任意選取一個數(shù)據(jù)(通常選用數(shù)組的第一個數(shù))作為關鍵數(shù)據(jù),然后將所有比它小的數(shù)都放到它前面,所有比它大的數(shù)都放到它后面,這個過程稱為一趟快速排序,之后再遞歸排序兩邊的數(shù)據(jù)


          Jave 版實現(xiàn)

          public?class?QuickSort?{
          ????public?static?void?quickSort(int[]?arr,int?low,int?high){
          ????????int?i,j,temp,t;
          ????????if(low>high){
          ????????????return;
          ????????}
          ????????i=low;
          ????????j=high;
          ????????//temp就是基準位
          ????????temp?=?arr[low];
          ?
          ????????while?(i????????????//先看右邊,依次往左遞減
          ????????????while?(temp<=arr[j]&&i????????????????j--;
          ????????????}
          ????????????//再看左邊,依次往右遞增
          ????????????while?(temp>=arr[i]&&i????????????????i++;
          ????????????}
          ????????????//如果滿足條件則交換
          ????????????if?(i????????????????t?=?arr[j];
          ????????????????arr[j]?=?arr[i];
          ????????????????arr[i]?=?t;
          ????????????}
          ?
          ????????}
          ????????//最后將基準為與i和j相等位置的數(shù)字交換
          ?????????arr[low]?=?arr[i];
          ?????????arr[i]?=?temp;
          ????????//遞歸調用左半數(shù)組
          ????????quickSort(arr,?low,?j-1);
          ????????//遞歸調用右半數(shù)組
          ????????quickSort(arr,?j+1,?high);
          ????}
          ?
          ?
          ????public?static?void?main(String[]?args){
          ????????int[]?arr?=?{10,7,2,4,7,62,3,4,2,1,8,9,19};
          ????????quickSort(arr,?0,?arr.length-1);
          ????????for?(int?i?=?0;?i?????????????System.out.println(arr[i]);
          ????????}
          ????}
          }

          Python 版實現(xiàn)

          def?quick_sort(data):
          ????if?not?data:
          ????????return?data
          ????first?=?data[0]
          ????left?=?quick_sort([l?for?l?in?data[1:]?if?l?????right?=?quick_sort([r?for?r?in?data[1:]?if?r?>=?first])
          ????return?left?+?[first]?+?right

          相比冒泡排序,快速排序每次交換是跳躍式的。每次排序的時候設置一個基準點,將小于等于基準點的數(shù)全部放到基準點的左邊,將大于等于基準點的數(shù)全部放到基準點的右邊。這樣在每次交換的時候就不會像冒泡排序一樣每次只能在相鄰的數(shù)之間進行交換,交換的距離就大的多了。因此總的比較和交換次數(shù)就少了,速度自然就提高了,時間復雜度為 O(N*logN)

          3直接插入排序

          插入排序的思想是把一個數(shù)據(jù)插入到一個有序序列中,從而得到一個新的序列加一的有序序列,可以通過下圖來進一步加深理解


          Java 版實現(xiàn)

          public?static?void?InsertSort(int[]?arr)
          {
          ????int?i,?j;
          ????int?n?=?arr.Length;
          ????int?target;
          ?
          ????//假定第一個元素被放到了正確的位置上
          ????//這樣,僅需遍歷1?-?n-1
          ????for?(i?=?1;?i?????{
          ????????j?=?i;
          ????????target?=?arr[i];
          ?
          ????????while?(j?>?0?&&?target?1])
          ????????{
          ????????????arr[j]?=?arr[j?-?1];
          ????????????j--;
          ????????}
          ?
          ????????arr[j]?=?target;
          ????}
          }

          Python 版實現(xiàn)

          def?insert_sort(data,?reverse=False):
          ????if?not?reverse:
          ????????for?i?in?range(1,?len(data)):
          ????????????key?=?data[i]
          ????????????j?=?i?-?1
          ????????????while?j?>=?0:
          ????????????????if?data[j]?>?key:
          ????????????????????data[j+1]?=?data[j]
          ????????????????????data[j]?=?key
          ????????????????j?-=?1
          ????????return?data
          ????else:
          ????????for?i?in?range(1,?len(data)):
          ????????????key?=?data[i]
          ????????????j?=?i?-?1
          ????????????while?j?>=?0:
          ????????????????if?data[j]?????????????????????data[j+1]?=?data[j]
          ????????????????????data[j]?=?key
          ????????????????j?-=?1
          ????????return?data

          由于每次遍歷有序序列時,都會有序列中所有的數(shù)據(jù)做對比,故而時間復雜度為O(n^2)

          4選擇排序

          選擇排序,是逐個確定元素位置的思想。同樣是 n 遍循環(huán),第一輪時,每一個元素都與第一個元素比較,如果比第一個元素大,則與之交換,這樣一輪過后,第一個元素就是最小的了,第二輪開始每個元素與第二個位置的元素比較,如果大,則與第二位置的元素交換,以此類推,達到排序的目的


          Java 版實現(xiàn)

          public?static?int[]?selectionSort(int[]?array)?{
          ????int?len?=?array.length;
          ????//?如果數(shù)組長度為0或者1,都是不用排序直接返回
          ????if(len?==?0?||?len?==?1)?{
          ????????return?array;
          ????}
          ????for(int?i?=?0;?i?1;?i++)?{
          ????????int?minIdx?=?i;
          ????????for(int?j?=?i?+?1;?j?????????????//?找到最小的數(shù)
          ????????????if(array[minIdx]?>?array[j])?{
          ????????????????//?保存最小數(shù)的索引
          ????????????????minIdx?=?j;
          ????????????}
          ????????}
          ????????//?如果一輪比較下來都沒有變更最小值的索引則無需調換順序
          ????????if(minIdx?!=?i)?{
          ????????????int?tmp?=?array[i];
          ????????????array[i]?=?array[minIdx];
          ????????????array[minIdx]?=?tmp;
          ????????}
          ????}
          ????return?array;
          }

          Python 版實現(xiàn)

          def?selection_sort(data,?reverse=False):
          ????"""
          ????:param?data:?list?type?data
          ????:param?reverse:
          ????:return:?list?type?data
          ????"""

          ????if?not?reverse:
          ????????for?i?in?range(len(data)-1):
          ????????????min_index?=?i
          ????????????for?j?in?range(i+1,?len(data)):
          ????????????????if?data[j]?????????????????????min_index?=?j
          ????????????data[i],?data[min_index]?=?data[min_index],?data[i]
          ????????return?data
          ????else:
          ????????for?i?in?range(len(data)?-?1):
          ????????????min_index?=?i
          ????????????for?j?in?range(i+1,?len(data)):
          ????????????????if?data[j]?>?data[min_index]:
          ????????????????????min_index?=?j
          ????????????data[i],?data[min_index]?=?data[min_index],?data[i]
          ????????return?data

          選擇排序和冒泡排序還是很相似的,但是選擇排序會比冒泡排序少一次交換的過程,但是同樣是兩層循環(huán),所有時間復雜度也是 O(n^2)

          5并歸排序

          可以把一個數(shù)組分成兩半,對于每一個數(shù)組當他們是有序的就可以進行一次合并操作。對于他們的兩個區(qū)間進行遞歸,一直遞歸下去劃分區(qū)間,當區(qū)間只有一個值的時候我們就可以進行合并返回上一層,讓上一層合并再返回


          Java 版實現(xiàn)

          public?static?int[]?sort(int[]?a,int?low,int?high){
          ????????int?mid?=?(low+high)/2;
          ????????if(low????????????sort(a,low,mid);
          ????????????sort(a,mid+1,high);
          ????????????//左右歸并
          ????????????merge(a,low,mid,high);
          ????????}
          ????????return?a;
          ????}
          ?????
          ????public?static?void?merge(int[]?a,?int?low,?int?mid,?int?high)?{
          ????????int[]?temp?=?new?int[high-low+1];
          ????????int?i=?low;
          ????????int?j?=?mid+1;
          ????????int?k=0;
          ????????//?把較小的數(shù)先移到新數(shù)組中
          ????????while(i<=mid?&&?j<=high){
          ????????????if(a[i]????????????????temp[k++]?=?a[i++];
          ????????????}else{
          ????????????????temp[k++]?=?a[j++];
          ????????????}
          ????????}
          ????????//?把左邊剩余的數(shù)移入數(shù)組?
          ????????while(i<=mid){
          ????????????temp[k++]?=?a[i++];
          ????????}
          ????????//?把右邊邊剩余的數(shù)移入數(shù)組
          ????????while(j<=high){
          ????????????temp[k++]?=?a[j++];
          ????????}
          ????????//?把新數(shù)組中的數(shù)覆蓋nums數(shù)組
          ????????for(int?x=0;x????????????a[x+low]?=?temp[x];
          ????????}
          ????}

          Python 版實現(xiàn)

          def?merge(a,?b):
          ????c?=?[]
          ????h?=?j?=?0
          ????while?j?and?h?????????if?a[j]?????????????c.append(a[j])
          ????????????j?+=?1
          ????????else:
          ????????????c.append(b[h])
          ????????????h?+=?1
          ?
          ????if?j?==?len(a):
          ????????for?i?in?b[h:]:
          ????????????c.append(i)
          ????else:
          ????????for?i?in?a[j:]:
          ????????????c.append(i)
          ?
          ????return?c
          ?
          ?
          def?merge_sort(lists):
          ????if?len(lists)?<=?1:
          ????????return?lists
          ????middle?=?len(lists)//2
          ????left?=?merge_sort(lists[:middle])
          ????right?=?merge_sort(lists[middle:])
          ????return?merge(left,?right)

          歸并排序采用分而治之的原理:首先將一個序列從中間位置分成兩個序列,然后再將這兩個子序列按照第一步繼續(xù)二分下去,最后直到所有子序列的長度都為1,也就是不可以再二分截止。這時候再兩兩合并成一個有序序列即可。時間復雜度 O(NlogN)

          6隨機快速排序

          隨機快速排序與快速排序的思路一樣,差異就是取主元之前,隨機快速排序多了一個步驟:隨機快速排序是隨機取得一個元素,并且會與最后一個元素交換位置。取得主元的下標位置實際上還是最后一個下標,快速排序是習慣取得最后一個元素作為主元


          Java 版實現(xiàn)

          package?quicksort;

          import?java.util.Random;

          public?class?RandomQuickSort?{

          ????public?void?Sort(int[]?a,?int?p,?int?r)?{
          ????????if?(p?????????????int?q?=?Partition(a,?p,?r);
          ????????????Sort(a,?p,?q-1);
          ????????????Sort(a,q+1,?r);
          ????????}
          ????}

          ????private?int?Partition(int[]?A,?int?p,?int?r)?{
          ????????/*隨機選取主元元素*/
          ????????Random?random?=?new?Random();
          ????????int?random_index?=?random.nextInt(r-p+1)+p;
          ????????System.out.println("random_index="+random_index);
          ????????int?temp?=?A[random_index];
          ????????A[random_index]?=?A[r];
          ????????A[r]?=?temp;

          ????????int?x?=?A[r];??//pivot?=?A[p]
          ????????int?i?=?p-1;
          ????????for?(int?j?=?p;?j?????????????if?(A[j]?<=?x)?{??//與pivot作比較
          ????????????????i++;
          ????????????????int?tmp?=?A[j];
          ????????????????A[j]?=?A[i];
          ????????????????A[i]?=?tmp;
          ????????????}
          ????????}

          ????????int?tmp?=?A[r];
          ????????A[r]?=?A[i+1];
          ????????A[i+1]?=?tmp;

          ????????return?i+1;

          ????}

          }

          Python 版實現(xiàn)

          import?random
          def?random_quicksort(a,left,right):
          ????if(left????????mid?=?random_partition(a,left,right)
          ????????random_quicksort(a,left,mid-1)
          ????????random_quicksort(a,mid+1,right)


          def?random_partition(a,left,right):?
          ????t?=?random.randint(left,right)?????#生成[left,right]之間的一個隨機數(shù)
          ????a[t],a[right]?=?a[right],a[t]????
          ????x?=?a[right]
          ????i?=?left-1?????????????????????????#初始i指向一個空,保證0到i都小于等于?x
          ????for?j?in?range(left,right):????????#j用來尋找比x小的,找到就和i+1交換,保證i之前的都小于等于x
          ????????if(a[j]<=x):
          ????????????i?=?i+1
          ????????????a[i],a[j]?=?a[j],a[i]
          ????a[i+1],a[right]?=?a[right],a[i+1]??#0到i?都小于等于x?,所以x的最終位置就是i+1
          ????return?i+1

          while(True):
          ????try:
          ????????s?=?input("輸入待排序數(shù)組:\n")?????????????#待排數(shù)組
          ????????l?=s.split()
          ????????a?=?[int(t)?for?t?in?l]
          ????????random_quicksort(a,0,len(a)-1)
          ????????print?("排序后:")
          ????????for?item?in?a:
          ????????????print(item,end=‘?‘)
          ????????print("\n")
          ????except:
          ????????break

          7計數(shù)排序

          首先統(tǒng)計原數(shù)組中每個值出現(xiàn)的次數(shù)

          然后進行排序:遍歷Count數(shù)組,對應位置的值出現(xiàn)多少次就往原數(shù)組寫幾個這個值

          當然,在對于數(shù)據(jù)比較大的時候我們可以通過相對映射,讓(該值-min)后的數(shù)組加一,最后還原回去即可


          Java 版實現(xiàn)

          public?static?int[]?CountingSort(int[]?a)?{
          ????int?b[]?=?new?int[a.length];
          ????int?max?=?a[0],?min?=?a[0];
          ????for?(int?i=1;i????????if?(a[i]?>?max)?{
          ????????????max?=?a[i];
          ????????}
          ????????if?(a[i]?????????min?=?a[i];
          ????????}
          ????}?
          ????//?k的大小是要排序的數(shù)組中,元素大小的極值差+1
          ????int?k?=?max?-?min?+?1;
          ????int?c[]?=?new?int[k];
          ????//統(tǒng)計A數(shù)組元素出現(xiàn)次數(shù)
          ????for?(int?i?=?0;?i?????????c[a[i]?-?min]?+=?1;
          ????}
          ????//更新計算C數(shù)組
          ????for?(int?i?=?1;?i?????????c[i]?=?c[i]?+?c[i?-?1];
          ????}
          ????//填充B數(shù)組
          ????for?(int?i?=?a.length?-?1;?i?>=?0;?--i)?{
          ????????b[--c[a[i]?-?min]]?=?a[i];
          ????}
          ????return?b;
          }

          Python 版實現(xiàn)

          def?countSort(arr):
          ????max_value?=?max(arr)
          ????res?=?[]
          ????count_nums?=?[0?for?i?in?range(max_value?+?1)]
          ????for?num?in?arr:
          ????????count_nums[num]?+=?1
          ????for?i?in?range(len(count)):
          ????????if?count_nums[i]?!=?0:
          #?元素i有?count_nums[i]個,添加入最終的排序數(shù)組
          ????????????res.extend(count_nums[i]?*?[i])
          ????return?res

          8基數(shù)排序

          基數(shù)排序核心思想是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次類推,直到最高位。有時候有些屬性是有優(yōu)先級順序的,先按低優(yōu)先級排序,再按高優(yōu)先級排序。最后的次序就是高優(yōu)先級高的在前,高優(yōu)先級相同的低優(yōu)先級高的在前


          Java 版實現(xiàn)

          public?class?RadixSort?{
          ????public?static?void?main(String[]?args)?{
          ????????int[]?arr?=?{63,?157,?189,?51,?101,?47,?141,?121,?157,?156,
          ????????????????194,?117,?98,?139,?67,?133,?181,?12,?28,?0,?109};

          ????????radixSort(arr);

          ????????System.out.println(Arrays.toString(arr));
          ????}

          ????/**
          ?????*?高位優(yōu)先法
          ?????*
          ?????*?@param?arr?待排序列,必須為自然數(shù)
          ?????*/

          ????private?static?void?radixSort(int[]?arr)?{
          ????????//待排序列最大值
          ????????int?max?=?arr[0];
          ????????int?exp;//指數(shù)

          ????????//計算最大值
          ????????for?(int?anArr?:?arr)?{
          ????????????if?(anArr?>?max)?{
          ????????????????max?=?anArr;
          ????????????}
          ????????}

          ????????//從個位開始,對數(shù)組進行排序
          ????????for?(exp?=?1;?max?/?exp?>?0;?exp?*=?10)?{
          ????????????//存儲待排元素的臨時數(shù)組
          ????????????int[]?temp?=?new?int[arr.length];
          ????????????//分桶個數(shù)
          ????????????int[]?buckets?=?new?int[10];

          ????????????//將數(shù)據(jù)出現(xiàn)的次數(shù)存儲在buckets中
          ????????????for?(int?value?:?arr)?{
          ????????????????//(value?/?exp)?%?10?:value的最底位(個位)
          ????????????????buckets[(value?/?exp)?%?10]++;
          ????????????}

          ????????????//更改buckets[i],
          ????????????for?(int?i?=?1;?i?10;?i++)?{
          ????????????????buckets[i]?+=?buckets[i?-?1];
          ????????????}

          ????????????//將數(shù)據(jù)存儲到臨時數(shù)組temp中
          ????????????for?(int?i?=?arr.length?-?1;?i?>=?0;?i--)?{
          ????????????????temp[buckets[(arr[i]?/?exp)?%?10]?-?1]?=?arr[i];
          ????????????????buckets[(arr[i]?/?exp)?%?10]--;
          ????????????}

          ????????????//將有序元素temp賦給arr
          ????????????System.arraycopy(temp,?0,?arr,?0,?arr.length);
          ????????}

          ????}
          }

          Python 版實現(xiàn)

          def?radixSort(arr):
          ????n?=?len(str(max(arr)))??#?記錄最大值的位數(shù)
          ????for?k?in?range(n):#n輪排序
          ????????#?每一輪生成10個列表
          ????????bucket_list=[[]?for?i?in?range(10)]#因為每一位數(shù)字都是0~9,故建立10個桶
          ????????for?i?in?arr:
          ????????????#?按第k位放入到桶中
          ????????????bucket_list[i//(10**k)%10].append(i)
          ????????#?按當前桶的順序重排列表
          ????????arr=[j?for?i?in?bucket_list?for?j?in?i]
          ????return?arr

          今天我們的排序算法就介紹到這里,后面我們還會更加深入的介紹其他數(shù)據(jù)結構和算法,不要錯過哦



          往期精彩回顧




          站qq群955171419,加入微信群請掃碼:


          瀏覽 53
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲男人天堂av 亚洲视频无码在线 | 特黄aaaaaaaa真人毛片 | 一道本无码免费 | 7777777色 | 亚洲视频在线观看不卡 |