在本文中,讨论了两种基数排序:
- LSD 基数排序:它从字符串的末尾(最低有效数字)开始排序。
- MSD 基数排序:从字符串的开头(最高位)开始排序。
在本文中,任务是讨论 MSD 基数排序并将其与 LSD 基数排序进行比较。
方法:我们的想法是执行针对每个数字以下步骤i其中i的值从最显著位到最低位显著变化:
- 根据第i个数字将元素存储在不同的桶中。
- 对包含多个元素的每个桶进行递归排序。
最高与最低有效数字基数排序:
- 这个想法是对固定长度的整数进行排序,MSD 比 LSD 更有效,因为它可能不必检查每个整数的每个数字:
LSD 基数排序:
MSD基数排序:
- 与 LSD 不同,MSD 可用于对可变长度的字符串进行排序。 LSD 必须稳定才能正常工作,但 MSD 可以变得稳定或不稳定,并且 MSD 可以处理随机字符串。
- 时间复杂度:
- LSD 基数排序:最佳和最坏情况时间复杂度为O(N*M) ,其中 M = 最长字符串的长度。
MSD 基数排序:最佳情况时间复杂度为O(N) ,最坏情况时间复杂度为O(N*M) ,其中 M =字符串的平均长度。
- LSD 基数排序:最佳和最坏情况时间复杂度为O(N*M) ,其中 M = 最长字符串的长度。
- 辅助空间:
- LSD基数排序: O(N + B)
- MSD 基数排序: O(N + MB ),其中 M = 最长字符串的长度,B = 基数的大小(B=10 个可能的数字或 B=256 个字符或 B=2 的二进制)。
- MSD 使用递归,因此它比 LSD 需要更多空间。这意味着在处理少量输入时,MSD 比 LSD 慢得多。
MSD基数排序的实现:
使用链表:此实现适用于使用链表的整数。每个节点的固定长度数组将占用非常大量的存储空间。
下面是使用链表实现 MSD 基数排序:
C++
// C++ program for the implementation
// of MSD Radix Sort using linked list
#include
#include
using namespace std;
// Linked list node structure
struct node {
vector arr;
struct node* nxt[10];
};
// Function to create a new node of
// the Linked List
struct node* new_node(void)
{
struct node* tempNode = new node;
for (int i = 0; i < 10; i++) {
tempNode->nxt[i] = NULL;
}
// Return the created node
return tempNode;
}
// Function to sort the given array
// using MSD Radix Sort recursively
void msd_sort(struct node* root, int exp,
vector& sorted_arr)
{
if (exp <= 0) {
return;
}
int j;
// Stores the numbers in different
// buckets according their MSD
for (int i = 0;
i < root->arr.size();
i++) {
// Get the MSD in j
j = (root->arr[i] / exp) % 10;
// If j-th index in the node
// array is empty create and
// link a new node in index
if (root->nxt[j] == NULL) {
root->nxt[j] = new_node();
}
// Store the number in j-th node
root->nxt[j]->arr.push_back(
root->arr[i]);
}
// Sort again every child node that
// has more than one number
for (int i = 0; i < 10; i++) {
// If root->next is NULL
if (root->nxt[i] != NULL) {
if (root->nxt[i]->arr.size()
> 1) {
// Sort recursively
msd_sort(root->nxt[i],
exp / 10,
sorted_arr);
}
// If any node have only
// one number then it means
// the number is sorted
else {
sorted_arr.push_back(
root->nxt[i]->arr[0]);
}
}
}
}
// Function to calculate the MSD of the
// maximum value in the array
int get_max_exp(vector arr)
{
// Stores the maximum element
int mx = arr[0];
// Traverse the given array
for (int i = 1; i < arr.size(); i++) {
// Update the value of maximum
if (arr[i] > mx) {
mx = arr[i];
}
}
int exp = 1;
while (mx > 10) {
mx /= 10;
exp *= 10;
}
// Return the resultant value
return exp;
}
// Function to print an array
void print(vector arr)
{
for (int i = 0; i < arr.size(); i++)
cout << arr[i] << " ";
cout << endl;
}
// Driver Code
int main()
{
// create the root node
struct node* root = new_node();
// Stores the unsorted array
// in the root node
root->arr.insert(root->arr.end(),
{ 9330, 9950, 718,
8977, 6790, 95,
9807, 741, 8586,
5710 });
cout << "Unsorted array : ";
// Print the unsorted array
print(root->arr);
// Find the optimal longest exponent
int exp = get_max_exp(root->arr);
// Stores the sorted numbers
vector sorted_arr;
// Function Call
msd_sort(root, exp, sorted_arr);
cout << "Sorted array : ";
// Print the sorted array
print(sorted_arr);
return 0;
}
C++
// C++ program for the implementation
// of MSD Radix Sort using counting sort()
#include
#include
using namespace std;
// Utility function to get the ASCII
// value of the character at index d
// in the string
int char_at(string str, int d)
{
if (str.size() <= d)
return -1;
else
return str.at(d);
}
// Function to sort the array using
// MSD Radix Sort recursively
void MSD_sort(string* str, int lo,
int hi, int d)
{
// Recursive break condition
if (hi <= lo) {
return;
}
// Stores the ASCII Values
int count[256 + 1] = { 0 };
// Temp is created to easily
// swap strings in str[]
unordered_map temp;
// Store the occurrences of the most
// significant character from
// each string in count[]
for (int i = lo; i <= hi; i++) {
int c = char_at(str[i], d);
count++;
}
// Change count[] so that count[]
// now contains actual position
// of this digits in temp[]
for (int r = 0; r < 256 + 1; r++)
count[r + 1] += count[r];
// Build the temp
for (int i = lo; i <= hi; i++) {
int c = char_at(str[i], d);
temp[count++] = str[i];
}
// Copy all strings of temp to str[],
// so that str[] now contains
// partially sorted strings
for (int i = lo; i <= hi; i++)
str[i] = temp[i - lo];
// Recursively MSD_sort() on each
// partially sorted strings set to
// sort them by their next character
for (int r = 0; r < 256; r++)
MSD_sort(str, lo + count[r],
lo + count[r + 1] - 1,
d + 1);
}
// Function to print an array
void print(string* str, int n)
{
for (int i = 0; i < n; i++) {
cout << str[i] << " ";
}
cout << endl;
}
// Driver Code
int main()
{
// Input String
string str[] = { "midnight", "badge",
"bag", "worker",
"banner", "wander" };
// Size of the string
int n = sizeof(str) / sizeof(str[0]);
cout << "Unsorted array : ";
// Print the unsorted array
print(str, n);
// Function Call
MSD_sort(str, 0, n - 1, 0);
cout << "Sorted array : ";
// Print the sorted array
print(str, n);
return 0;
}
Java
// Java program for the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
public class GFG {
// Utility function to get the ASCII
// value of the character at index d
// in the string
static int char_at(String str, int d)
{
if (str.length() <= d)
return -1;
else
return (int)(str.charAt(d));
}
// Function to sort the array using
// MSD Radix Sort recursively
static void MSD_sort(String str[], int lo, int hi,
int d)
{
// Recursive break condition
if (hi <= lo) {
return;
}
// Stores the ASCII Values
int count[] = new int[256 + 1];
// Temp is created to easily
// swap strings in str[]
HashMap temp = new HashMap<>();
// Store the occurrences of the most
// significant character from
// each string in count[]
for (int i = lo; i <= hi; i++) {
int c = char_at(str[i], d);
count++;
}
// Change count[] so that count[]
// now contains actual position
// of this digits in temp[]
for (int r = 0; r < 256; r++)
count[r + 1] += count[r];
// Build the temp
for (int i = lo; i <= hi; i++) {
int c = char_at(str[i], d);
temp.put(count++, str[i]);
}
// Copy all strings of temp to str[],
// so that str[] now contains
// partially sorted strings
for (int i = lo; i <= hi; i++)
str[i] = temp.get(i - lo);
// Recursively MSD_sort() on each
// partially sorted strings set to
// sort them by their next character
for (int r = 0; r < 256; r++)
MSD_sort(str, lo + count[r],
lo + count[r + 1] - 1, d + 1);
}
// Function to print an array
static void print(String str[], int n)
{
for (int i = 0; i < n; i++) {
System.out.print(str[i] + " ");
}
System.out.println();
}
// Driver Code
public static void main(String[] args)
{
// Input String
String str[] = { "midnight", "badge", "bag",
"worker", "banner", "wander" };
// Size of the string
int n = str.length;
System.out.print("Unsorted array : ");
// Print the unsorted array
print(str, n);
// Function Call
MSD_sort(str, 0, n - 1, 0);
System.out.print("Sorted array : ");
// Print the sorted array
print(str, n);
}
}
// This code is contributed by Kingash.
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG{
// Utility function to get the ASCII
// value of the character at index d
// in the string
static int char_at(String str, int d)
{
if (str.Length <= d)
return -1;
else
return(int)(str[d]);
}
// Function to sort the array using
// MSD Radix Sort recursively
static void MSD_sort(String []str, int lo,
int hi, int d)
{
// Recursive break condition
if (hi <= lo)
{
return;
}
// Stores the ASCII Values
int []count = new int[256 + 1];
// Temp is created to easily
// swap strings in []str
Dictionary temp = new Dictionary();
// Store the occurrences of the most
// significant character from
// each string in []count
for(int i = lo; i <= hi; i++)
{
int c = char_at(str[i], d);
count++;
}
// Change []count so that []count
// now contains actual position
// of this digits in []temp
for(int r = 0; r < 256; r++)
count[r + 1] += count[r];
// Build the temp
for(int i = lo; i <= hi; i++)
{
int c = char_at(str[i], d);
temp.Add(count++, str[i]);
}
// Copy all strings of temp to []str,
// so that []str now contains
// partially sorted strings
for(int i = lo; i <= hi; i++)
str[i] = temp[i - lo];
// Recursively MSD_sort() on each
// partially sorted strings set to
// sort them by their next character
for(int r = 0; r < 256; r++)
MSD_sort(str, lo + count[r],
lo + count[r + 1] - 1,
d + 1);
}
// Function to print an array
static void print(String []str, int n)
{
for(int i = 0; i < n; i++)
{
Console.Write(str[i] + " ");
}
Console.WriteLine();
}
// Driver Code
public static void Main(String[] args)
{
// Input String
String []str = { "midnight", "badge", "bag",
"worker", "banner", "wander" };
// Size of the string
int n = str.Length;
Console.Write("Unsorted array : ");
// Print the unsorted array
print(str, n);
// Function Call
MSD_sort(str, 0, n - 1, 0);
Console.Write("Sorted array : ");
// Print the sorted array
print(str, n);
}
}
// This code is contributed by shikhasingrajput
输出:
Unsorted array : 9330 9950 718 8977 6790 95 9807 741 8586 5710
Sorted array : 95 718 741 5710 6790 8586 8977 9330 9807 9950
使用 Counting Sort() 方法:此实现适用于基于计数 sort() 方法的字符串。由于 C 风格的 ASCII字符是1 个字节。因此, 256 大小的数组用于计算字符的出现次数,并按字典顺序对字符串排序。
下面是使用计数 sort() 方法实现 MSD 基数排序:
C++
// C++ program for the implementation
// of MSD Radix Sort using counting sort()
#include
#include
using namespace std;
// Utility function to get the ASCII
// value of the character at index d
// in the string
int char_at(string str, int d)
{
if (str.size() <= d)
return -1;
else
return str.at(d);
}
// Function to sort the array using
// MSD Radix Sort recursively
void MSD_sort(string* str, int lo,
int hi, int d)
{
// Recursive break condition
if (hi <= lo) {
return;
}
// Stores the ASCII Values
int count[256 + 1] = { 0 };
// Temp is created to easily
// swap strings in str[]
unordered_map temp;
// Store the occurrences of the most
// significant character from
// each string in count[]
for (int i = lo; i <= hi; i++) {
int c = char_at(str[i], d);
count++;
}
// Change count[] so that count[]
// now contains actual position
// of this digits in temp[]
for (int r = 0; r < 256 + 1; r++)
count[r + 1] += count[r];
// Build the temp
for (int i = lo; i <= hi; i++) {
int c = char_at(str[i], d);
temp[count++] = str[i];
}
// Copy all strings of temp to str[],
// so that str[] now contains
// partially sorted strings
for (int i = lo; i <= hi; i++)
str[i] = temp[i - lo];
// Recursively MSD_sort() on each
// partially sorted strings set to
// sort them by their next character
for (int r = 0; r < 256; r++)
MSD_sort(str, lo + count[r],
lo + count[r + 1] - 1,
d + 1);
}
// Function to print an array
void print(string* str, int n)
{
for (int i = 0; i < n; i++) {
cout << str[i] << " ";
}
cout << endl;
}
// Driver Code
int main()
{
// Input String
string str[] = { "midnight", "badge",
"bag", "worker",
"banner", "wander" };
// Size of the string
int n = sizeof(str) / sizeof(str[0]);
cout << "Unsorted array : ";
// Print the unsorted array
print(str, n);
// Function Call
MSD_sort(str, 0, n - 1, 0);
cout << "Sorted array : ";
// Print the sorted array
print(str, n);
return 0;
}
Java
// Java program for the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
public class GFG {
// Utility function to get the ASCII
// value of the character at index d
// in the string
static int char_at(String str, int d)
{
if (str.length() <= d)
return -1;
else
return (int)(str.charAt(d));
}
// Function to sort the array using
// MSD Radix Sort recursively
static void MSD_sort(String str[], int lo, int hi,
int d)
{
// Recursive break condition
if (hi <= lo) {
return;
}
// Stores the ASCII Values
int count[] = new int[256 + 1];
// Temp is created to easily
// swap strings in str[]
HashMap temp = new HashMap<>();
// Store the occurrences of the most
// significant character from
// each string in count[]
for (int i = lo; i <= hi; i++) {
int c = char_at(str[i], d);
count++;
}
// Change count[] so that count[]
// now contains actual position
// of this digits in temp[]
for (int r = 0; r < 256; r++)
count[r + 1] += count[r];
// Build the temp
for (int i = lo; i <= hi; i++) {
int c = char_at(str[i], d);
temp.put(count++, str[i]);
}
// Copy all strings of temp to str[],
// so that str[] now contains
// partially sorted strings
for (int i = lo; i <= hi; i++)
str[i] = temp.get(i - lo);
// Recursively MSD_sort() on each
// partially sorted strings set to
// sort them by their next character
for (int r = 0; r < 256; r++)
MSD_sort(str, lo + count[r],
lo + count[r + 1] - 1, d + 1);
}
// Function to print an array
static void print(String str[], int n)
{
for (int i = 0; i < n; i++) {
System.out.print(str[i] + " ");
}
System.out.println();
}
// Driver Code
public static void main(String[] args)
{
// Input String
String str[] = { "midnight", "badge", "bag",
"worker", "banner", "wander" };
// Size of the string
int n = str.length;
System.out.print("Unsorted array : ");
// Print the unsorted array
print(str, n);
// Function Call
MSD_sort(str, 0, n - 1, 0);
System.out.print("Sorted array : ");
// Print the sorted array
print(str, n);
}
}
// This code is contributed by Kingash.
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG{
// Utility function to get the ASCII
// value of the character at index d
// in the string
static int char_at(String str, int d)
{
if (str.Length <= d)
return -1;
else
return(int)(str[d]);
}
// Function to sort the array using
// MSD Radix Sort recursively
static void MSD_sort(String []str, int lo,
int hi, int d)
{
// Recursive break condition
if (hi <= lo)
{
return;
}
// Stores the ASCII Values
int []count = new int[256 + 1];
// Temp is created to easily
// swap strings in []str
Dictionary temp = new Dictionary();
// Store the occurrences of the most
// significant character from
// each string in []count
for(int i = lo; i <= hi; i++)
{
int c = char_at(str[i], d);
count++;
}
// Change []count so that []count
// now contains actual position
// of this digits in []temp
for(int r = 0; r < 256; r++)
count[r + 1] += count[r];
// Build the temp
for(int i = lo; i <= hi; i++)
{
int c = char_at(str[i], d);
temp.Add(count++, str[i]);
}
// Copy all strings of temp to []str,
// so that []str now contains
// partially sorted strings
for(int i = lo; i <= hi; i++)
str[i] = temp[i - lo];
// Recursively MSD_sort() on each
// partially sorted strings set to
// sort them by their next character
for(int r = 0; r < 256; r++)
MSD_sort(str, lo + count[r],
lo + count[r + 1] - 1,
d + 1);
}
// Function to print an array
static void print(String []str, int n)
{
for(int i = 0; i < n; i++)
{
Console.Write(str[i] + " ");
}
Console.WriteLine();
}
// Driver Code
public static void Main(String[] args)
{
// Input String
String []str = { "midnight", "badge", "bag",
"worker", "banner", "wander" };
// Size of the string
int n = str.Length;
Console.Write("Unsorted array : ");
// Print the unsorted array
print(str, n);
// Function Call
MSD_sort(str, 0, n - 1, 0);
Console.Write("Sorted array : ");
// Print the sorted array
print(str, n);
}
}
// This code is contributed by shikhasingrajput
输出:
Unsorted array : midnight badge bag worker banner wander
Sorted array : badge bag banner midnight wander worker
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live