问题:设计一个算法在O(n)时间内,对0到n^3-1区间内的数进行排序。
此问题是基数排序的应用,也用到了桶排序。思路如下:
可以将数字用n进制表示,那么0到n^3-1中的数最多是n进制的三位数。这样可以建立n个桶按照次位优先的规则排序3次即可。所以总时间是O(n+n+n)=O(n);例如当n=4时,n^3-1=63,有4个数的数列为54,2,63,15;在排序时首先用4进制表示该数。如54表示为4进制的关键字为key[0]=2,key[1]=1,key[2]=3,因为54=2+1*4+3*4^2;将这些数字依次按照key[0],key[1],key[2]排序即可得到结果,以下代码用n=5来测试,
#include<iostream>
using namespace std;
class Node{
public:
int key[3];
Node*next;
};
typedef Node*PNode;
PNode conver(int a[], int n);
PNode Radix_sort(PNode head, int n);
void Show_Node(PNode head,int n);
int main(){
const int n =5;
int a[n] = { 89,120,45,1,56 };
PNode head = conver(a,n);
head = Radix_sort(head, n);
Show_Node(head,n);
return 0;
}
PNode conver(int a[], int n){ //关键字分解,使其串为链表
PNode head=new Node; //作用为空头结点
PNode p = head,p1=head;
int i;
for (i = 0; i < n; i++){
p = new Node;
p->key[0] = a[i] % n;
p->key[1] = a[i] / n%n;
p->key[2] = a[i] / n / n%n;
p1->next = p;
p1 = p1->next;
}
p1->next = nullptr;
p = head;
head = head->next;
delete p;
return head;
}
PNode Radix_sort(PNode head,int n){
int i, j;
PNode *Bucket= new PNode[n]; //建立n个桶,记录n个桶首元素位置
PNode *Rear = new PNode[n]; //记录每个桶末尾元素位置
for (i = 0; i < 3; i++){;
for (j = 0; j < n; j++)
Bucket[j]= Rear[j] =nullptr;
while (head){
if (Bucket[head->key[i]]){ //桶若不空
Rear[head->key[i]]->next = head;
Rear[head->key[i]] = Rear[head->key[i]]->next;
}
else
Bucket[head->key[i]] = Rear[head->key[i]]=head;
head = head->next;
}
j = 0;
while (!Bucket[j]) j++; //找到头结点
head = Bucket[j];
PNode rear = Rear[j];
for (j = j + 1; j < n; j++){ //将桶中节点串接起来
if (Bucket[j]){
rear->next = Bucket[j];
rear = Rear[j];
}
}
rear->next = nullptr; //未结点指向空非常重要
}
return head;
}
void Show_Node(PNode head,int n){//显示链表结果
while (head){
cout << head->key[0] + head->key[1] * n + head->key[2] * n*n << " ";
head = head->next;
}
}