數據結構與演算法之非比較排序【Java】

来源:https://www.cnblogs.com/Demrystv/archive/2018/05/10/9022204.html
-Advertisement-
Play Games

比較排序與非比較排序的對比 常見的快速排序、歸併排序、堆排序、冒泡排序等屬於比較排序。在排序的最終結果里,元素之間的次序依賴於它們之間的比較。每個數都必須和其他數進行比較,才能確定自己的位置。在冒泡排序之類的排序中,問題規模為n,又因為需要比較n次,所以平均時間複雜度為O(n²)。在歸併排序、快速排 ...


比較排序與非比較排序的對比

  常見的快速排序、歸併排序、堆排序、冒泡排序等屬於比較排序。在排序的最終結果里,元素之間的次序依賴於它們之間的比較。每個數都必須和其他數進行比較,才能確定自己的位置。在冒泡排序之類的排序中,問題規模為n,又因為需要比較n次,所以平均時間複雜度為O(n²)。在歸併排序、快速排序之類的排序中,問題規模通過分治法消減為logN次,所以時間複雜度平均O(nlogn)。比較排序的優勢是,適用於各種規模的數據,也不在乎數據的分佈,都能進行排序。可以說,比較排序適用於一切需要排序的情況。

計數排序、基數排序、桶排序則屬於非比較排序。非比較排序是通過確定每個元素之前,應該有多少個元素來排序。針對數組arr,計算arr[i]之前有多少個元素,則唯一確定了arr[i]在排序後數組中的位置。

  非比較排序只要確定每個元素之前的已有的元素個數即可,所有一次遍歷即可解決。演算法時間複雜度O(n)。非比較排序時間複雜度底,但由於非比較排序需要占用空間來確定唯一位置。所以對數據規模和數據分佈有一定的要求。

 

非比較排序

常見的比較排序主要有以下幾種:基數排序、計數排序、桶排序。

 

基數排序

1、基本思想:將所有待比較數值(正整數)統一為同樣的數位長度,數位較短的數前面補零。然後,從最低位開始,依次進行一次排序。這樣從最低位排序一直到最高位排序完成以後,數列就變成一個有序序列。

2、演算法實現

 

 1 package com.allSorts;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 /**
 7  * Created by Demrystv.
 8  */
 9 public class Ji1Shu {
10     public static void main(String[] args) {
11         int[] a = {23,45,67,88,90,21,42,52,73,61};
12         System.out.println("排序前:");
13         for(int i=0;i<a.length;i++){
14             System.out.print(a[i]+" ");
15         }
16 
17         //基數排序
18         sort(a);
19 
20         System.out.println("");
21         System.out.println("排序後:");
22         for(int i=0;i<a.length;i++){
23             System.out.print(a[i]+" ");
24         }
25     }
26 
27     private static void sort(int[] a){
28 
29         //找到最大值,看最大值有幾位,從而確定要比較幾次,個十百千萬。。。
30         int max = 0;
31         for(int i=0;i<a.length;i++){
32             if(max<a[i]){
33                 max = a[i];
34             }
35         }
36 
37         //找到最大值後,確定要比較幾次
38         int times = 0;
39         while (max>0){
40             max = max/10;
41             times++;
42         }
43 
44         //建立從0到9十個隊列
45         List<ArrayList> list1 = new ArrayList<>();
46         for(int i=0;i<10;i++){
47             ArrayList list2 = new ArrayList();
48             list1.add(list2);
49         }
50 
51         //進行times次分配和收集,不斷的重覆即可。
52         for(int i=0;i<times;i++){
53 
54             //分配,按照比較的所在的位的大小將其放入list1 中,類似於數組鏈表中的鏈表
55             for(int j=0;j<a.length;j++){
56                 int x = a[j] % (int)Math.pow(10,i+1) / (int)Math.pow(10,i);
57                 ArrayList list3 = list1.get(x);
58                 list3.add(a[j]);
59                 list1.set(x,list3);
60             }
61 
62             //收集,然後以此從數組的從左到右,鏈表的從上到下進行收集,將其重新放進一個新的數組中
63             int count = 0 ;
64             for(int j=0;j<10;j++){
65                 while (list1.get(j).size()>0){
66                     ArrayList<Integer> list4 = list1.get(j);
67                     a[count] = list4.get(0);
68                     list4.remove(0);
69                     count++;
70                 }
71             }
72         }
73 
74 
75     }
76 }

 

3、分析

  基數排序是穩定的排序演算法。

  基數排序的時間複雜度為O(k*n),空間複雜度為O(m),k為數組中數值的最大位數,m為桶的的個數。

 

計數排序

1、基本思想是:對每一個輸入的元素arr[i],確定小於 arr[i] 的元素個數,可以直接把 arr[i] 放到它輸出數組中的位置上。假設有x個數小於 arr[i],所以 arr[i] 應該放在數組的第(x+1)個位置上。 2、演算法實現
 1 package com.allSorts;
 2 
 3 /**
 4  * Created by Demrystv.
 5  */
 6 public class Ji4Shu {
 7     public static void main(String[] args) {
 8         int[] a = {23,42,53,64,63,32,13,52,97,94,26};
 9         System.out.println("排序前:");
10         for(int i=0;i<a.length;i++){
11             System.out.print(a[i]+" ");
12         }
13 
14         //計數排序
15         sort(a);
16 
17         System.out.println("");
18         System.out.println("排序後:");
19         for(int i=0;i<a.length;i++){
20             System.out.print(a[i]+" ");
21         }
22     }
23 
24     private static void sort(int[] a){
25 
26         if(a==null || a.length==0){
27             return;
28         }
29 
30         int max=0,min=0;
31         for(int i=0;i<a.length;i++){
32             max = Math.max(max,a[i]);
33             min = Math.min(min,a[i]);
34         }
35 
36         int[] help = new int[max-min+1];
37         int pos;
38 
39         for(int i=0;i<a.length;i++){
40             pos = a[i]-min;
41             help[pos]++;
42         }
43 
44         int index=0;
45         for(int i=0;i<help.length;i++){
46             while (help[i]>0){
47                 a[index] = i + min;
48                 index++;
49                 help[i]--;
50             }
51         }
52     }
53 }

 

3、分析

  計數排序是穩定的排序演算法。

  計數排序的時間複雜度為O(k+n),空間複雜度為O(m),k為數組中最大數與最小數差值,m為桶的的個數。

 

桶排序

1、基本思想是把數組 arr 劃分為n個大小相同子區間(桶),每個子區間各自排序,最後合併。計數排序是桶排序的一種特殊情況,可以把計數排序當成每個桶里只有一個元素的情況。 2、演算法實現
 1 package com.allSorts;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Collections;
 5 
 6 /**
 7  * Created by Demrystv.
 8  */
 9 public class Tong {
10     public static void main(String[] args) {
11         int[] a = {32,45,42,51,53,86,95,53,93,55,59};
12         System.out.println("排序前:");
13         for(int i=0;i<a.length;i++){
14             System.out.print(a[i]+" ");
15         }
16 
17         //桶排序
18         sort(a);
19 
20         System.out.println("");
21         System.out.println("排序後:");
22         for(int i=0;i<a.length;i++){
23             System.out.print(a[i]+" ");
24         }
25     }
26 
27     private static void sort(int[] a){
28 
29         if(a==null || a.length==0){
30             return;
31         }
32 
33         int max=0,min=0;
34         for(int i=0;i<a.length;i++){
35             max = Math.max(max,a[i]);
36             min = Math.min(min,a[i]);
37         }
38 
39         //確定桶數,並且建立一系列的桶
40         int bucketNum = (max-min)/a.length+1;
41         ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
42         for (int i=0;i<bucketNum;i++){
43             bucketArr.add(new ArrayList<Integer>());
44         }
45 
46         //將每個元素放入桶
47         for(int i=0;i<a.length;i++){
48             int num = (a[i]-min)/a.length;
49             bucketArr.get(num).add(a[i]);
50         }
51 
52         //對每個桶進行排序
53         for(int i=0;i<bucketArr.size();i++){
54             Collections.sort(bucketArr.get(i));
55         }
56 
57         int index = 0;
58         for(int i=0;i<bucketArr.size();i++){
59             while (bucketArr.get(i).size()>0){
60                 a[index++] = bucketArr.get(i).get(0);
61                 bucketArr.get(i).remove(0);
62             }
63         }
64     }
65 }

 

3、分析

桶排序可用於最大最小值相差較大的數據情況,。 但桶排序要求數據的分佈必須均勻,否則可能導致數據都集中到一個桶中,導致桶排序失效。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • https://www.cnblogs.com/xFreedom/archive/2011/05/16/2048037.html https://blog.csdn.net/major_zhang/article/details/52117608 相信使用過MFC編程的朋友對CString這個類的印 ...
  • 參考網路上代碼編輯而成,無技術含量,可自行定製: 目前親測有效,若有待完善之處,還望指出! 強調:將此統計py腳本放置項目的根目錄下執行即可。 1、遍歷文件,遞歸遍歷文件夾中的所有 2、指定文件類型:項目的代碼行數,故只考慮.py文件,當然也可在指定的文件類型列表whitelist中添加其他類型 3 ...
  • 例子 當我們訪問Facebook網站,需要代理伺服器A(翻/牆)才能夠訪問。當代理伺服器A訪問Facebook,Facebook也不老實,用代理伺服器B來隱藏自己的後端伺服器,A訪問的是B。 A:正向代理 B:反向代理 圖例 在知乎中看正向代理與反向代理的解釋,有張圖覺得解釋不錯,但可能導致誤解,於 ...
  • 找房子找的頭都大了,價格翻倍,而且面積小,質量差! 公司的項目倒不算太忙但是學習方面很忙,腦力明顯不足了! 自己的引擎依然處於停滯狀態! 虛幻的格鬥倒是有一點進度,不過還是卡在用藍圖來實現複雜的多重迴圈時邏輯總調不對! 新找的房子不太滿意,乾濕分離的玻璃門沒有了用一個簾來代替,門鎖是密碼的,從裡面能 ...
  • 一、 伺服器server的寫法: 1. 創建 socket 套接字:網路編程介面 socket(family = AF_INET , type = SOCKET_STREM,proto = 0, fileno = None) 提供了多種socket family。AF_INET 是預設的family ...
  • 第一步:dubbo-monitor-simple-2.5.3 連上zookeeper註冊中心,獲得要調用的介面的ip和埠號 第二步:輸入命令:telnet 192.168.x.xxx xxxxx 回車後如果顯示 :Escape character is '^]'. 代表連接成功,正在監聽dubbo ...
  • 一、分散式架構 1、分散式特點 分佈性 對等性。分散式系統中的所有電腦節點都是對等的 併發性。多個節點併發的操作一些共用的資源 缺乏全局時鐘。節點之間通過消息傳遞進行通信和協調,因為缺乏全局時鐘,很難定義兩個事件誰先誰後 故障總是會發生。系統設計時,需要考慮到任何異常情況 2、分散式環境的各種問題 ...
  • 官方的說法: classmethod(function) 中文說明: classmethod是用來指定一個類的方法為類方法,沒有此參數指定的類的方法為實例方法,使用方法如下: 看後之後真是一頭霧水。說的啥子東西呢??? 自己到國外的論壇看其他的例子和解釋,頓時就很明朗。 下麵自己用例子來說明。 看下 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...