赞
踩
问题的由来:最近在做一些算法题时,涉及到对字符串进行排序,网上查阅了大量文章感觉都没有对此问题有一个明确的说法,索性自己做实验并总结出一定的规律,方便自己也方便他人。
问题的抽象:考虑对n个字符串(字符串均由可打印字符组成,具体而言十进制码值位于[32,126]这个区间)进行升序排序,输出排序后的字符串情况,并分析时间复杂度。
问题的思考过程:以下面的ASCII码表为依据,从字符串的长度以及字符串的组成类型两个角度来思考排序时的比较规则。
- #include<iostream>
- #include<vector>
- #include<algorithm>
- using namespace std;
-
- int main()
- {
- vector<string> vc = {"a", "b", "abc", "ad", "aba", "bdc"};
- vector<string> vc1 = {"0", "5", "110", "12", "101", "567"};
-
- sort(vc.begin(), vc.end());
- sort(vc1.begin(), vc1.end());
-
- for(auto &x : vc) {
- cout << x << " ";
- }
- cout << endl;
- for(auto &x : vc1) {
- cout << x << " ";
- }
-
- return 0;
- }
【程序结果及分析】
由结果可知,当字符串的字符组成为同一类型,排序时所采用的比较准则是“从左至右依次比较每个字符,当字符不同时将码值较小者置于前面,当字符相同时则继续向后比较,直至每个字符都进行了比对(有提前结束者,则认为更小)”。
这种情况是第一种情况的特例,不存在比较时某个字符串提前结束的情况,从左至右挨个比较即可。
- #include<iostream>
- #include<vector>
- #include<algorithm>
- using namespace std;
-
- int main()
- {
- vector<string> vc = {"aac", "4ba", "A0B", "adf", "?56", "11a"};
-
- sort(vc.begin(), vc.end());
-
- for(auto &x : vc) {
- cout << x << " ";
- }
-
- return 0;
- }
【程序结果及分析】
先大致对ASCII码表的符号分布有一个大致印象:一些标点符号以及四则运算符分布在数字0~9的前后,A~Z紧跟着的不是数字而是@和?号,小写字母与大写字母之间也间隔着一些其他标点符号。
此时,对于字符串的字符类型不同,但长度相同的情况,依然是从左至右的挨个比较字符,并将码值较小者置于前面。
- #include<iostream>
- #include<vector>
- #include<algorithm>
- using namespace std;
-
- int main()
- {
- vector<string> vc = {"a", "4b", "A0B", "adffg", "?56", "1!a", "10a"};
-
- sort(vc.begin(), vc.end());
-
- for(auto &x : vc) {
- cout << x << " ";
- }
-
- return 0;
- }
【程序结果及分析】
此时,对于字符串的字符类型不同,且长度不同的情况,规则于第一种情况相同:从左至右依次比较每个字符,当字符不同时将码值较小者置于前面,当字符相同时则继续向后比较,直至每个字符都进行了比对(有提前结束者,则认为更小)。
【结论】
上述的分析从字符串组成类型以及字符串长度两个角度出发,探讨了四种情况下的排序规则。总的来说,不考虑类型和长度的情况下,规则基本上都是:从左至右依次比较每个字符,当字符不同时将码值较小者置于前面,当字符相同时则继续向后比较,直至每个字符都进行了比对(有提前结束者,则认为更小)。
另外,对字符串进行快速排序(与对int型数据排序不同),不能单纯的认为时间复杂度就为O(nlogn),还需要考虑字符串的平均长度(假定为m),即在排序的过程中还要完成对字符串中m个字符的比对,故整体的时间复杂度应为O(m*nlogn)。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。