內部排序演算法5(基數排序)
基數排序
多排序碼排序的概念
如果每個元素的排序碼都是由多個數據項組成的組項,則依據它進行排序時就需要利用多排序碼排序。實現多排序碼排序有兩種常用的方法,最高位優先(Most Significant Digit (MSD) First)和最低位優先(Least Signnificant Digit(LSD) first)。利用多排序碼排序實現對單個排序碼排序的演算法就稱為基數排序。
MSD基數排序
思想
在基數排序中,將單排序碼
在排序過程中,首先是根據
步驟
- 演算法要求事先設定Radix個桶,Radix叫做基數,即排序碼的每一位可能取值的數目。為了知道每個桶中會有多少個元素,在演算法中還設定了一個輔助陣列
count[Radix] ,用count[k] 記憶在處理第i 位時第i 位取值為k 的元素有多少個。k 與基數Radix 有關。如果k 屬於十進位制整數,Radix 等於10。例如,在上圖中當i=1 時,count 各陣列元素記憶了不同取值的元素個數,c 表示值為0的元素有1個,count[3]=2 表示值為3的元素有2個。 - 在演算法中還使用了一個輔助陣列
auxArray[] 存放按桶分配的結果,根據count[] 預先算定各桶元素的使用位置。在每一趟向各桶分配結束時,元素都被複制回原表中。
演算法實現
#pragma once
#include<iostream>
#define RADIX 10
class MSDRaixSort
{
public:
MSDRaixSort(int length);
void create();
void sort();
void print();
~MSDRaixSort();
private :
int *elem;
int len;
void radixSort(int left, int right, int d);
int getDigit(int num, int d);
};
MSDRaixSort::MSDRaixSort(int length)
{
len = length;
elem = new int[len];
}
inline void MSDRaixSort::create()
{
std::cout << "please input the list" << std::endl;
for (int i = 0; i < len; i++)
{
int temp;
std::cin >> temp;
elem[i] = temp;
}
std::cout << "finish!" << std::endl;
}
inline void MSDRaixSort::sort()
{
radixSort(0, len - 1, 3);
}
inline void MSDRaixSort::print()
{
for (int i = 0; i < len; i++)
{
std::cout << elem[i] << " ";
}
std::cout << std::endl;
}
MSDRaixSort::~MSDRaixSort()
{
delete[] elem;
}
inline void MSDRaixSort::radixSort(int left, int right, int d) //MSD基數排序演算法,從高位到低位對序列進行分配,實現排序
{ //其中d時位數,n時待排序元素的個數。left和right時待排序
int i, j, count[RADIX + 1], p1, p2; //元素子序列的始端和尾端,最低位d=1,最高位是d
int *auxArray = new int[right - left + 1];
if (d <= 0)
{
return;
}
for (j = 0; j < RADIX; j++)
{
count[j] = 0;
}
for (i = left; i <= right; i++) //統計各桶元素的個數
{
count[getDigit(elem[i], d)]++;
}
count[RADIX] = right - left + 1;
for (j = 1; j < RADIX; j++) //安排各桶元素位置
{
count[j] = count[j] + count[j - 1];
}
for (i = left; i <= right; ++i) {
j = getDigit(elem[i], d);
auxArray[count[j] - 1] = elem[i];
--count[j];
}
for (i = left, j = 0; i <= right; j++, i++) //從輔助陣列auxArray寫入原陣列。
{
elem[i] = auxArray[j];
}
for (j = 0; j < RADIX; j++) //將各桶內的元素迭代進行MSD基數排序,直到桶內只有一個元素為止。
{
p1 = count[j];
p2 = count[j + 1] - 1;
if (p1 < p2)
{
radixSort(p1, p2, d - 1);
}
}
}
inline int MSDRaixSort::getDigit(int num, int d)
{
int count = 0;
while (num > 0) {
count++;
if (count == d)
{
return num % 10;
}
num = num / 10;
}
return 0;
}
//MSD基數排序main檔案
using namespace std;
#include"MSDRadixSorting.h"
int main() {
MSDRaixSort m(15);
m.create();
m.sort();
m.print();
system("pause");
}
演算法分析
時間複雜度
在演算法中呼叫一個getDigit按位獲取用來排序的元素排序碼。在上述例子中,從高位到低位一次取待排序元素的各位作為排序碼,並設定排序的基數RADIX為10。這就相當於定義了10個接收器,分別接受不同排序碼對應的待排序元素。如果待排序元素序列的規模為n,則每個接收器中的待排元素平局為
空間複雜度
在演算法中用到了兩個陣列,一個是
演算法的穩定性
MSD基數排序演算法是穩定的。
LSD基數排序
思想
LSD基數排序抽取排序碼的順序和MSD基數排序正好相反。使用這種方法,把單排序碼
如果對於所有元素的排序碼
各個桶都採用鏈式佇列結構,分配到同一桶的排序碼用連結指標連結起來。每一個桶設定兩個佇列指標:一個指向隊頭(第一個進入此佇列的排序碼),記為
待排序的
演算法的實現
//LSD基數排序演算法標頭檔案
#pragma once
#include<iostream>
#define Radix 10
struct ElementType
{
int data;
int link;
};
class LSDRadixSort
{
public:
LSDRadixSort(int length);