给定一个大小为n的数字数组。还假定数组元素的范围是0到n 2 –1。以线性时间对给定数组进行排序。
例子:
Since there are 5 elements, the elements can be from 0 to 24.
Input: arr[] = {0, 23, 14, 12, 9}
Output: arr[] = {0, 9, 12, 14, 23}
Since there are 3 elements, the elements can be from 0 to 8.
Input: arr[] = {7, 0, 2}
Output: arr[] = {0, 2, 7}
解决方案:如果使用计数排序,由于给定范围的大小为n ^ 2,因此将花费O(n ^ 2)时间。使用任何基于比较的排序(例如合并排序,堆排序等)将花费O(nLogn)时间。
现在出现问题了,如何在0(n)中执行此操作?首先,有可能吗?我们可以使用有问题的数据吗? n个数字,范围从0到n 2 – 1?
这个想法是使用基数排序。以下是标准的Radix Sort算法。
1) Do following for each digit i where i varies from least
significant digit to the most significant digit.
…………..a) Sort input array using counting sort (or any stable
sort) according to the i’th digit
设输入整数为d位。基数排序需要O(d *(n + b))时间,其中b是表示数字的基数,例如对于十进制,b是10。由于n 2 -1是最大可能值,所以d的值将是是O(log b (n))。因此,总体时间复杂度为O((n + b)* O(log b (n))。它看起来比基于比较的排序算法对大k的时间复杂度高。想法是更改基数b。 b作为n,O(log b (n))的值变为O(1),总时间复杂度变为O(n)。
arr[] = {0, 10, 13, 12, 7}
Let us consider the elements in base 5. For example 13 in
base 5 is 23, and 7 in base 5 is 12.
arr[] = {00(0), 20(10), 23(13), 22(12), 12(7)}
After first iteration (Sorting according to the last digit in
base 5), we get.
arr[] = {00(0), 20(10), 12(7), 22(12), 23(13)}
After second iteration, we get
arr[] = {00(0), 12(7), 20(10), 22(12), 23(13)}
以下是对大小为n的数组进行排序的实现,其中元素的范围为0到n 2 – 1。
C++
#include
using namespace std;
// A function to do counting sort of arr[] according to
// the digit represented by exp.
int countSort(int arr[], int n, int exp)
{
int output[n]; // output array
int i, count[n] ;
for (int i=0; i < n; i++)
count[i] = 0;
// Store count of occurrences in count[]
for (i = 0; i < n; i++)
count[ (arr[i]/exp)%n ]++;
// Change count[i] so that count[i] now contains actual
// position of this digit in output[]
for (i = 1; i < n; i++)
count[i] += count[i - 1];
// Build the output array
for (i = n - 1; i >= 0; i--)
{
output[count[ (arr[i]/exp)%n] - 1] = arr[i];
count[(arr[i]/exp)%n]--;
}
// Copy the output array to arr[], so that arr[] now
// contains sorted numbers according to current digit
for (i = 0; i < n; i++)
arr[i] = output[i];
}
// The main function to that sorts arr[] of size n using Radix Sort
void sort(int arr[], int n)
{
// Do counting sort for first digit in base n. Note that
// instead of passing digit number, exp (n^0 = 1) is passed.
countSort(arr, n, 1);
// Do counting sort for second digit in base n. Note that
// instead of passing digit number, exp (n^1 = n) is passed.
countSort(arr, n, n);
}
// A utility function to print an array
void printArr(int arr[], int n)
{
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
}
// Driver program to test above functions
int main()
{
// Since array size is 7, elements should be from 0 to 48
int arr[] = {40, 12, 45, 32, 33, 1, 22};
int n = sizeof(arr)/sizeof(arr[0]);
cout << "Given array is n";
printArr(arr, n);
sort(arr, n);
cout << "nSorted array is n";
printArr(arr, n);
return 0;
}
Java
// Java program to sort an array of size n where elements are
// in range from 0 to n^2 – 1.
class Sort1ToN2
{
// A function to do counting sort of arr[] according to
// the digit represented by exp.
void countSort(int arr[], int n, int exp)
{
int output[] = new int[n]; // output array
int i, count[] = new int[n] ;
for (i=0; i < n; i++)
count[i] = 0;
// Store count of occurrences in count[]
for (i = 0; i < n; i++)
count[ (arr[i]/exp)%n ]++;
// Change count[i] so that count[i] now contains actual
// position of this digit in output[]
for (i = 1; i < n; i++)
count[i] += count[i - 1];
// Build the output array
for (i = n - 1; i >= 0; i--)
{
output[count[ (arr[i]/exp)%n] - 1] = arr[i];
count[(arr[i]/exp)%n]--;
}
// Copy the output array to arr[], so that arr[] now
// contains sorted numbers according to current digit
for (i = 0; i < n; i++)
arr[i] = output[i];
}
// The main function to that sorts arr[] of size n using Radix Sort
void sort(int arr[], int n)
{
// Do counting sort for first digit in base n. Note that
// instead of passing digit number, exp (n^0 = 1) is passed.
countSort(arr, n, 1);
// Do counting sort for second digit in base n. Note that
// instead of passing digit number, exp (n^1 = n) is passed.
countSort(arr, n, n);
}
// A utility function to print an array
void printArr(int arr[], int n)
{
for (int i = 0; i < n; i++)
System.out.print(arr[i]+" ");
}
// Driver program to test above functions
public static void main(String args[])
{
Sort1ToN2 ob = new Sort1ToN2();
// Since array size is 7, elements should be from 0 to 48
int arr[] = {40, 12, 45, 32, 33, 1, 22};
int n = arr.length;
System.out.println("Given array");
ob.printArr(arr, n);
ob.sort(arr, n);
System.out.println("Sorted array");
ob.printArr(arr, n);
}
}
/*This code is contributed by Rajat Mishra */
Python3
# Python3 the implementation to sort an
# array of size n
# A function to do counting sort of arr[]
# according to the digit represented by exp.
def countSort(arr, n, exp):
output = [0] * n # output array
count = [0] * n
for i in range(n):
count[i] = 0
# Store count of occurrences in count[]
for i in range(n):
count[ (arr[i] // exp) % n ] += 1
# Change count[i] so that count[i] now contains
# actual position of this digit in output[]
for i in range(1, n):
count[i] += count[i - 1]
# Build the output array
for i in range(n - 1, -1, -1):
output[count[ (arr[i] // exp) % n] - 1] = arr[i]
count[(arr[i] // exp) % n] -= 1
# Copy the output array to arr[], so that
# arr[] now contains sorted numbers according
# to current digit
for i in range(n):
arr[i] = output[i]
# The main function to that sorts arr[] of
# size n using Radix Sort
def sort(arr, n) :
# Do counting sort for first digit in base n.
# Note that instead of passing digit number,
# exp (n^0 = 1) is passed.
countSort(arr, n, 1)
# Do counting sort for second digit in base n.
# Note that instead of passing digit number,
# exp (n^1 = n) is passed.
countSort(arr, n, n)
# Driver Code
if __name__ =="__main__":
# Since array size is 7, elements should
# be from 0 to 48
arr = [40, 12, 45, 32, 33, 1, 22]
n = len(arr)
print("Given array is")
print(*arr)
sort(arr, n)
print("Sorted array is")
print(*arr)
# This code is contribute by
# Shubham Singh(SHUBHAMSINGH10)
C#
// C# program to sort an array of
// size n where elements are
// in range from 0 to n^2 – 1.
using System;
class GFG {
// A function to do counting
// sort of arr[] according to
// the digit represented by exp.
static void countSort(int[] arr,
int n,
int exp)
{
// output array
int[] output = new int[n];
int[] count = new int[n] ;
int i;
for (i = 0; i < n; i++)
count[i] = 0;
// Store count of
// occurrences in count[]
for (i = 0; i < n; i++)
count[(arr[i] / exp) % n ]++;
// Change count[i] so that
// count[i] now contains actual
// position of this digit in output[]
for (i = 1; i < n; i++)
count[i] += count[i - 1];
// Build the output array
for (i = n - 1; i >= 0; i--)
{
output[count[(arr[i] /
exp) % n] - 1] = arr[i];
count[(arr[i] / exp) % n]--;
}
// Copy the output array to
// arr[], so that arr[] now
// contains sorted numbers
// according to current digit
for (i = 0; i < n; i++)
arr[i] = output[i];
}
// The main function to that
// sorts arr[] of size n
// using Radix Sort
static void sort(int[] arr, int n)
{
// Do counting sort for first
// digit in base n. Note that
// instead of passing digit number,
// exp (n^0 = 1) is passed.
countSort(arr, n, 1);
// Do counting sort for second
// digit in base n. Note that
// instead of passing digit number,
// exp (n^1 = n) is passed.
countSort(arr, n, n);
}
// A utility function
// to print an array
static void printArr(int[] arr, int n)
{
for (int i = 0; i < n; i++)
Console.Write(arr[i] + " ");
}
// Driver Code
static public void Main ()
{
// Since array size is 7,
// elements should be
// from 0 to 48
int[] arr = {40, 12, 45, 32, 33, 1, 22};
int n = arr.Length;
Console.WriteLine("Given array");
printArr(arr, n);
sort(arr, n);
Console.WriteLine("\nSorted array");
printArr(arr, n);
}
}
// This code is contributed by Ajit.
Javascript
输出:
Given array is
40 12 45 32 33 1 22
Sorted array is
1 12 22 32 33 40 45
如果范围是1到n 2怎么排序?
如果范围是1到nn 2 ,则不能直接应用上述过程,必须对其进行更改。考虑n = 100,范围从1到10000。由于基数是100,所以数字必须在0到99之间,并且数字中应该有2个数字。但是数字10000有2位以上的数字。因此,要对1到n 2范围内的数字进行排序,我们可以使用以下过程。
1)用1减去所有数字。
2)由于范围现在是0到n 2 ,因此请像上面的实现一样对计数进行两次计数。
3)元素排序后,将所有数字加1以获得原始数字。