算法导论-8-3-排序不同长度的数据项
来源:互联网 发布:灰度梯度共生矩阵 编辑:程序博客网 时间:2024/06/05 12:46
一、题目
a)给定一个整数数组,其中不同的整数中包含的数字个数可能不同,但是该数组中,所有整数中总的数字数为n。说明如何在O(n)时间内对该数组进行排序
b)给定一个字符串数组,其中不同的串包含的字符个数可能不同,但所有串中总的字符个数为n。说明如何在O(n)时间内对该数组进行排序
(注意此处的顺序是指标准的字母顺序,例如,a < ab < b)
二、思路
a)先用计数排序算法按数字位数排序O(n),再用基数排序的方法分别对每个桶中的元素排序O(n)
b)递归使用计数排序,先依据第一个字母进行排序,首字相同的放在同一组,再对每一组分别使用计数排序的方法比较第二个字母
见到有人用字典树,也是可以的,见算法导论-12-2-基数树
三、代码
a)
- //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;
- }
//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)
- #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;
- }
#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;elseD[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)
转载自:http://blog.csdn.net/mishifangxiangdefeng/article/details/7686099
- 算法导论8-3思考题-排序长度不同的数据项
- 算法导论-8-3-排序不同长度的数据项
- 算法导论-8-3-排序不同长度的数据项
- 算法导论-8-3-排序不同长度的数据项
- 算法导论习题8-3—排序不同长度的数据项
- 排序不同长度的数据项
- 排序不同长度的数据项
- 算法导论 8-3思考题 之变长数据项的排序
- 算法导论8-3变长数据项排序-整数数组-字符串
- 8-3变长数据项的排序
- 更新sql server数据项的长度
- 《算法导论》的堆排序
- 算法导论学习心得1-----插入排序及两种不同插入方法的效率比较
- 不同长度的字符串数组排序
- 《算法导论的Java实现》 8 快速排序
- 《算法导论》排序算法
- 《算法导论》排序算法
- 《算法导论》 上的计数排序
- ECmall邀请注册功能构想和实现
- 寄存器、RAM、ROM、Flash相关概念区别整理
- Android学习笔记(三三):Activity生命周期
- 数据库无法启动,报错shared memory realm already exists
- myeclipse src目录浏览方式设置
- 算法导论-8-3-排序不同长度的数据项
- 解决“RichEdit line insertion error”错误
- 固态继电器电路分析
- gcc编译 载录。。。。
- awk 手册
- 水仙花数
- Android学习笔记(三五):再谈Intent(下)-一些实践
- 微软之33 在O(1)的时间内删除链表的节点
- ns学习之-ns2的安装