數據結構與演算法之非比較排序【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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...