您的位置:首页 > 其它

算法导论-8-3-排序不同长度的数据项

2013-05-31 16:18 155 查看


算法导论-8-3-排序不同长度的数据项

分类: 算法导论2012-06-23
15:14 298人阅读 评论(2) 收藏 举报

算法deletestringc测试ie

目录(?)[+]


一、题目

a)给定一个整数数组,其中不同的整数中包含的数字个数可能不同,但是该数组中,所有整数中总的数字数为n。说明如何在O(n)时间内对该数组进行排序

b)给定一个字符串数组,其中不同的串包含的字符个数可能不同,但所有串中总的字符个数为n。说明如何在O(n)时间内对该数组进行排序

(注意此处的顺序是指标准的字母顺序,例如,a < ab < b)


二、思路

a)先用计数排序算法按数字位数排序O(n),再用基数排序的方法分别对每个桶中的元素排序O(n)
b)递归使用计数排序,先依据第一个字母进行排序,首字相同的放在同一组,再对每一组分别使用计数排序的方法比较第二个字母
见到有人用字典树,也是可以的,见算法导论-12-2-基数树


三、代码


a)

[cpp] view
plaincopy

//8-2-a

#include <iostream>

#include <cmath>

using namespace std;

int length_A;

void Print(int *A)

{

int i;

for(i = 1; i <= length_A; i++)

cout<<A[i]<<' ';

cout<<endl;

}

int Digit(int x)

{

int ret = 0;

while(x)

{

ret++;

x = x / 10;

}

return ret;

}

//基数排序调用的稳定排序

void Counting_Sort(int *A, int *B, int k)

{

int i, j;

//将C数组初始化为0,用于计数

int *C = new int[k+1];

for(i = 0; i <= k; i++)

C[i] = 0;

int *D = new int[length_A+1];

for(j = 1; j <= length_A; j++)

{

//D[j]表示第[j]个元素有i位数字

D[j] = Digit(A[j]);

//C[j]表示数字D[j]在数组A中出现的次数

C[D[j]]++;

}

//C[i]表示所以<=i的数字出现过的次数

for(i = 1; i <= k; i++)

C[i] = C[i] + C[i-1];

//初始化B为0,B用于输出排序结果

for(i = 1; i <= length_A; i++)

B[i] = 0;

for(j = length_A; j >= 1; j--)

{

//如果<=D[j]的数字的个数是x,那么排序后A[j]应该出现在第x个位置,即B[x]=A[j]

B[C[D[j]]] = A[j];

C[D[j]]--;

}

delete []C;

delete []D;

}

//基数排序调用的稳定排序

void Stable_Sort(int *A, int *B, int k, int d,int start, int end)

{

int i, j, radix = 10;

//将C数组初始化为0,用于计数

int *C = new int[k+1];

for(i = 0; i <= k; i++)

C[i] = 0;

int *D = new int[length_A+1];

for(j = start; j <= end; j++)

{

//D[j]表示第[j]个元素的第i位数字

D[j] = A[j] % (int)pow(radix*1.0, d) / (int)pow(radix*1.0, d-1);

//C[j]表示数字D[j]在数组A中出现的次数

C[D[j]]++;

}

//C[i]表示所以<=i的数字出现过的次数

for(i = 1; i <= k; i++)

C[i] = C[i] + C[i-1];

//初始化B为0,B用于输出排序结果

for(i = 1; i <= length_A; i++)

B[i] = 0;

for(j = end; j >= start; j--)

{

//如果<=D[j]的数字的个数是x,那么排序后A[j]应该出现在第x个位置,即B[x]=A[j]

B[C[D[j]]+start-1] = A[j];

C[D[j]]--;

}

delete []C;

delete []D;

}

void Radix_Sort(int *A, int *B, int k ,int digit, int start, int end)

{

int i, j;

//依次对每一位进行排序,从低位到高位

for(i = 1; i <= digit; i++)

{

Stable_Sort(A, B, k, i, start, end);

//输入的是A,输出的是B,再次排序时要把输出数据放入输出数据中

for(j = start; j <= end; j++)

A[j] = B[j];

}

}

int main()

{

cin>>length_A;

int i;

//产生随机的测试数据

int *A = new int[length_A+1];

for(i = 1; i <= length_A; i++)

A[i] = rand() % (int)pow(10.0, rand()%5+1);

Print(A);

int *B = new int[length_A+1];

//先进行计数排序,把长度相同的数字排在一起

Counting_Sort(A, B, 5);

for(i = 1; i <= length_A; i++)

A[i] = B[i];

Print(A);

int start, end, digit = -1;

for(i = 1; i <= length_A; i++)

{

if(digit == -1)

{

digit = Digit(A[i]);

start = i;

end = i;

}

else

{

if(Digit(A[i]) == digit)

end = i;

else

{

//找到位数相同的一段,从start到end,单独对这一段进行基数排序

Radix_Sort(A, B, 9, digit, start, end);

i--;

digit = -1;

Print(A);

}

}

}

delete []A;

delete []B;

}


b)

[cpp] view
plaincopy

#include <iostream>

#include <string>

using namespace std;

int length_A;

void Print(string *A)

{

int i;

for(i = 1; i <= length_A; i++)

cout<<A[i]<<' ';

cout<<endl;

}

//基数排序调用的稳定排序,A是输入,B是中间输出,C是计数,d表示对第d位字母排序,start和end分别是排序段的起点和终点

void Counting_Sort(string *A, string *B, int *C, int d, int start, int end)

{

if(start == end)

return;

int i, j;

//将C数组初始化为0,用于计数

for(i = 0; i <= 26; i++)

C[i] = 0;

int *D = new int[length_A+1];

for(j = start; j <= end; j++)

{

//D[j]表示第[j]个元素的第i位数字

if(A[j].length() <= d)

D[j] = 0;

else

D[j] = A[j][d] - 'a';

//C[j]表示数字D[j]在数组A中出现的次数

C[D[j]]++;

}

//C[i]表示所以<=i的数字出现过的次数

for(i = 1; i <= 26; i++)

C[i] = C[i] + C[i-1];

//初始化B为0,B用于输出排序结果

for(i = 1; i <= length_A; i++)

B[i] = "";

for(j = end; j >= start; j--)

{

//如果<=D[j]的数字的个数是x,那么排序后A[j]应该出现在第x个位置,即B[x]=A[j]

B[C[D[j]]+start-1] = A[j];

C[D[j]]--;

}

delete []D;

//输出转为输入

for(i = start; i <= end; i++)

A[i] = B[i];

char c = 'A';

int s, e;//进一步的排序以s为起点,e为终点

//对于排序的这一段,对下一个字母递归使用计数排序

for(i = start; i <= end; i++)

{

//如果长度为d,不参与下一步排序

if(A[i][d] == '\0')

continue;

if(c == 'A')

{

s = i;

e = i;

c = A[i][d];

}

else

{

if(A[i][d] == c)

{

e = i;

if(e == end)

//以第d+1位字母为依据,对s-e段进行计数排序

Counting_Sort(A, B, C, d+1, s, e);

}

else

{

//以第d+1位字母为依据,对s-e段进行计数排序

Counting_Sort(A, B, C, d+1, s, e);

i--;

c = 'A';

}

}

}

}

int main()

{

int i, j;

cin>>length_A;

string *A = new string[length_A+1];

//构造随机数据

for(i = 1; i <= length_A; i++)

{

int len = rand()%5+1;

for(j = 1; j <= len; j++)

A[i] = A[i] + (char)(rand()%26+'a');

}

Print(A);

string *B = new string[length_A+1];

int *C = new int[26];

//计数排序

Counting_Sort(A, B, C, 0, 1, length_A);

Print(A);

delete []A;

delete []C;

return 0;

}

四、效果:

a)



b)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: