算法记录:MSD基数排序 + qsort 对字符串排序
2008-02-20 01:42
393 查看
typedef std::vector<std::string> t_vstr;
void exch(std::string &str1, std::string &str2)
{
std::swap(str1, str2);
}
void str_qsort_internal(t_vstr &arr, int l, int r, size_t d)
{
if(l >= r)return;
int i = l - 1, j = r;
int p = i, q = j;
char v = arr[r][d];
while(i < j)
{
while(arr[++i][d] < v); //i是第一个大于等于v的索引,可能等于r(到r时一定停止循环)
while(v < arr[--j][d]) {if(j == l) break; } //j是第一个小于等于v的,当j == l时循环也会结束,例如所有元素都比arr[r]大
if(i > j) break;
exch(arr[i], arr[j]); //交换,要么是arr[i] >= v && arr[j] <= v 之后 arr[i] <= v && arr[j] >= v
if(arr[i][d] == v) exch(arr[i], arr[++p]);//arr[p]一定小于等于v,
if(arr[j][d] == v) exch(arr[j], arr[--q]); //arr[q]一定大于等于v
}
if(p == q)//如果p == q则证明l -> r区间全相等
{
if(v != '/0')str_qsort_internal(arr, l, r, d + 1);//如果不为字符串结尾,则转换到下一层,如果v为'/0'则证明排序完毕
return;
}
if(arr[i][d] < v)i++;
/*
下面两个移动算法类似下图
p
4,4,4,1,2,3
k j
3,4,4,1,2,4
k j
3,2,4,1,4,4
k j
3,2,1,4,4,4
j 4
p
4,4,4,4,2
k j
2,4,4,4,4
k j
2,4,4,4,4
kj
2,4,4,4,4
j k
*/
for(int k = l; k <= p; ++k, --j) exch(arr[k], arr[j]); //l -> j区间元素都是小于等于v的,而l -> p都是等于v的,
for(int k = r; k >= q; --k, ++i) exch(arr[k], arr[i]); //i->r区间元素都是大于等于v的,而i->r都是等于v的
str_qsort_internal(arr, l, j, d);//因为i -> j区间内不一定都是相同的,但一定都小于等于v
if((i == r) && (arr[i][d] == v)) i++;//这里,如果i == r && arr[i][d] == v,则证明从j + 1到 r都是相同的元素,所以i+=1照应下一步的 i - 1 和str_qsort_internal(arr, i, r, d);因为i + 1之后,i 就一定大于r了
if(v != '/0') str_qsort_internal(arr, j + 1, i - 1, d+1);//如果v == 0,那么j+1 -> i-1区间内的所有字符串都为结尾,所以无需递归排序了
str_qsort_internal(arr, i, r, d);//同理,因为i -> 区间内不应定都是相同的,但一定都大于等于v, 因此搜索层次还是d
}
void print_vstr(const t_vstr &vstr)
{
for(size_t i = 0; i < vstr.size(); ++i)
{
printf("%s/n", vstr[i].c_str());
}
}
int main()
{
t_vstr vstr;
vstr.push_back("9");
vstr.push_back("123");
vstr.push_back("232");
vstr.push_back("234");
vstr.push_back("456");
vstr.push_back("789");
vstr.push_back("259");
vstr.push_back("257");
str_qsort_internal(vstr, 0, vstr.size() - 1, 0);
print_vstr(vstr);
printf("done/n");
cin.get();
return 0;
};
void exch(std::string &str1, std::string &str2)
{
std::swap(str1, str2);
}
void str_qsort_internal(t_vstr &arr, int l, int r, size_t d)
{
if(l >= r)return;
int i = l - 1, j = r;
int p = i, q = j;
char v = arr[r][d];
while(i < j)
{
while(arr[++i][d] < v); //i是第一个大于等于v的索引,可能等于r(到r时一定停止循环)
while(v < arr[--j][d]) {if(j == l) break; } //j是第一个小于等于v的,当j == l时循环也会结束,例如所有元素都比arr[r]大
if(i > j) break;
exch(arr[i], arr[j]); //交换,要么是arr[i] >= v && arr[j] <= v 之后 arr[i] <= v && arr[j] >= v
if(arr[i][d] == v) exch(arr[i], arr[++p]);//arr[p]一定小于等于v,
if(arr[j][d] == v) exch(arr[j], arr[--q]); //arr[q]一定大于等于v
}
if(p == q)//如果p == q则证明l -> r区间全相等
{
if(v != '/0')str_qsort_internal(arr, l, r, d + 1);//如果不为字符串结尾,则转换到下一层,如果v为'/0'则证明排序完毕
return;
}
if(arr[i][d] < v)i++;
/*
下面两个移动算法类似下图
p
4,4,4,1,2,3
k j
3,4,4,1,2,4
k j
3,2,4,1,4,4
k j
3,2,1,4,4,4
j 4
p
4,4,4,4,2
k j
2,4,4,4,4
k j
2,4,4,4,4
kj
2,4,4,4,4
j k
*/
for(int k = l; k <= p; ++k, --j) exch(arr[k], arr[j]); //l -> j区间元素都是小于等于v的,而l -> p都是等于v的,
for(int k = r; k >= q; --k, ++i) exch(arr[k], arr[i]); //i->r区间元素都是大于等于v的,而i->r都是等于v的
str_qsort_internal(arr, l, j, d);//因为i -> j区间内不一定都是相同的,但一定都小于等于v
if((i == r) && (arr[i][d] == v)) i++;//这里,如果i == r && arr[i][d] == v,则证明从j + 1到 r都是相同的元素,所以i+=1照应下一步的 i - 1 和str_qsort_internal(arr, i, r, d);因为i + 1之后,i 就一定大于r了
if(v != '/0') str_qsort_internal(arr, j + 1, i - 1, d+1);//如果v == 0,那么j+1 -> i-1区间内的所有字符串都为结尾,所以无需递归排序了
str_qsort_internal(arr, i, r, d);//同理,因为i -> 区间内不应定都是相同的,但一定都大于等于v, 因此搜索层次还是d
}
void print_vstr(const t_vstr &vstr)
{
for(size_t i = 0; i < vstr.size(); ++i)
{
printf("%s/n", vstr[i].c_str());
}
}
int main()
{
t_vstr vstr;
vstr.push_back("9");
vstr.push_back("123");
vstr.push_back("232");
vstr.push_back("234");
vstr.push_back("456");
vstr.push_back("789");
vstr.push_back("259");
vstr.push_back("257");
str_qsort_internal(vstr, 0, vstr.size() - 1, 0);
print_vstr(vstr);
printf("done/n");
cin.get();
return 0;
};
相关文章推荐
- [算法] 关于algs4 MSD.java 高位优先的字符串排序 的逐行代码解释
- 【WEISS算法书】MSD基数排序
- 小白学算法3.1——低位优先字符串排序
- 算法导论之排序:快速排序、归并排序、计数排序、基数排序、桶排序
- 无聊时总结总结算法之09基数排序
- 算法学习记录-排序——快速排序
- Java算法之基数排序
- 桶式排序与基数排序举例及JAVA代码实现(附:基数排序的方法给英文字符串排序)
- 数据结构-算法: 分配排序(基数分配排序法)
- 字符串排序等算法
- 算法导论8.3基数排序底层计数排序
- STL学习记录(十三):排序类算法及基于排序的算法
- 第十六周 项目1验证算法-基数排序
- 第十六周项目1-(8)验证算法基数排序
- 经典算法:基数排序的小例子
- Hark的数据结构与算法练习之基数排序
- [算法] 基数排序
- Java排序算法以及算法改进总结(计数排序、基数排序、桶排序)
- 第16周SHH数据结构-【项目1-验证算法(8)基数排序 】
- 设计一个算法将两个字符串合并按字母排序