算法记录:MSD基数排序 + qsort 对字符串排序

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;
};

 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值