程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 深刻解析Radix Sort基數排序算法思惟及C說話完成示例

深刻解析Radix Sort基數排序算法思惟及C說話完成示例

編輯:關於C++

深刻解析Radix Sort基數排序算法思惟及C說話完成示例。本站提示廣大學習愛好者:(深刻解析Radix Sort基數排序算法思惟及C說話完成示例)文章只能為提供參考,不一定能成為您想要的結果。以下是深刻解析Radix Sort基數排序算法思惟及C說話完成示例正文


根本思惟:

將待排數據中的每組症結字順次停止桶分派。
詳細示例:

278、109、063、930、589、184、505、269、008、083

我們將每一個數值的個位,十位,百位分紅三個症結字: 278 -> k1(個位)=8,k2(十位)=7,k3=(百位)=2。

然後從最低位個位開端(從最次症結字開端),對一切數據的k1症結字停止桶分派(由於,每一個數字都是 0-9的,是以桶年夜小為10),再順次輸入桶中的數據獲得上面的序列。

930、063、083、184、505、278、008、109、589、269

再對下面的序列接著停止針對k2的桶分派,輸入序列為:

505、008、109、930、063、269、278、083、184、589

最初針對k3的桶分派,輸入序列為:

008、063、083、109、184、269、278、505、589、930

效力剖析:

基數排序的機能比桶排序要略差。每次症結字的桶分派都須要O(N)的時光龐雜度,並且分派以後獲得新的症結字序列又須要O(N)的時光龐雜度。假設待排數據可以分為d個症結字,則基數排序的時光龐雜度將是O(d*2N) ,固然d要遠遠小於N,是以根本上照樣線性級其余。基數排序的空間龐雜度為O(N+M),個中M為桶的數目。普通來講N>>M,是以額定空間須要年夜概N個閣下。

然則,比較桶排序,基數排序每次須要的桶的數目其實不多。並且基數排序簡直不須要任何“比擬”操作,而桶排序在桶絕對較少的情形下,桶內多個數據必需停止基於比擬操作的排序。是以,在現實運用中,基數排序的運用規模加倍普遍。


舉例:
假定我們有一些二元組(a,b),要對它們停止以a為重要症結字,b的主要症結字的排序。我們可以先把它們先依照重要症結字排序,分紅重要症結字雷同的若干堆。然後,在依照主要症結值分離對每堆停止零丁排序。最初再把這些堆串聯到一路,使重要症結字較小的一堆排在下面。按這類方法的基數排序稱為MSD(Most Significant Dight)排序。

第二種方法是從最低有用症結字開端排序,稱為LSD(Least Significant Dight)排序。起首對一切的數據依照主要症結字排序,然後對一切的數據依照重要症結字排序。要留意的是,應用的排序算法必需是穩固的,不然就會撤消前一次排序的成果。因為不須要分堆對每堆零丁排序,LSD辦法常常比MSD簡略而開支小。下文引見的辦法全體是基於LSD的。

平日,基數排序要用到計數排序或許桶排序。應用計數排序時,須要的是Order數組。應用桶排序時,可以用鏈表的辦法直接求出排序後的次序。上面是一段用桶排序對二元組基數排序的法式:


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
using namespace std;
struct data
{
  int key[2];
};
struct linklist
{
  linklist *next;
  data value;
  linklist(data v,linklist *n):value(v),next(n){}
  ~linklist() {if (next) delete next;}
};
void BucketSort(data *A,int N,int K,int y)
{
  linklist *Bucket[101],*p;//樹立桶
  int i,j,k,M;
  M=K/100+1;
  memset(Bucket,0,sizeof(Bucket));
  for (i=1;i<=N;i++)
  {
    k=A[i].key[y]/M; //把A中的每一個元素依照的規模值放入對應桶中
    Bucket[k]=new linklist(A[i],Bucket[k]);
  }
  for (k=j=0;k<=100;k++)
  {
    for (p=Bucket[k];p;p=p->next) j++;
    for (p=Bucket[k],i=1;p;p=p->next,i++)
      A[j-i+1]=p->value; //把桶中每一個元素掏出
    delete Bucket[k];
  }
}
void RadixSort(data *A,int N,int K)
{
  for (int j=1;j>=0;j--) //從低優先到高優先 LSD
    BucketSort(A,N,K,j);
}
int main()
{
  int N=100,K=1000,i;
  data *A=new data[N+1];
  for (i=1;i<=N;i++)
  {
    A[i].key[0]=rand()%K+1;
    A[i].key[1]=rand()%K+1;
  }
  RadixSort(A,N,K);
  for (i=1;i<=N;i++)
    printf("(%d,%d) ",A[i].key[0],A[i].key[1]);
  printf("\n");
  return 0;
}

基數排序是一種用在老式穿卡機上的算法。一張卡片有80列,每列可在12個地位中的任一處穿孔。排序器可被機械地"法式化"以檢討每迭卡片中的某一列,再依據穿孔的地位將它們分放12個盒子裡。如許,操作員便可逐一地把它們搜集起來。個中第一個地位穿孔的放在最下面,第二個地位穿孔的其次,等等。

關於一個位數無限的十進制數,我們可以把它看做一個多元組,從高位到低位症結字主要水平順次遞加。可使用基數排序對一些位數無限的十進制數排序。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved