计数排序:时间复杂度O(n+k),空间复杂度O(k)

  • 问题描述

假设n个记录中每个关键字都介于0到k-1之间,修改计数排序算法,使得算法满足:

时间复杂度:O(n+k),空间复杂度:n+O(k)

  • 问题分析

原计数排序算法中,需借助另一个大小为n的数组进行排序,不能做到原地排序,如何实现原地排序?

原计数排序算法中,对数组中的每个元素,都已计算出了比其小或相等的元素个数,即确定了其最终位置。每个元素都已确定了自身的最终位置,但如何实现原地排序?

  • 解决思路

从数组最后一个元素array[array.size()-1]开始,将其交换至最终位置上,并对交换后的array[array.size()-1]继续执行此操作,直至该元素的最终位置即为此位置为止,此后,对下一个位置执行相同操作,直至执行至数组的第二个位置为止。

但存在一个问题,当数组存在相同元素时,若其中一个元素已在其最终位置A[j],当对另一个元素交换至其最终位置的过程中,发现其最终位置已存在与其相等的元素,此时,应将该元素交换至A[k]处,A[k]为从j往前的第一个不同于该元素的位置。

  • 实现代码

C++实现,其中数组用vector<pair<int, int> >存储,pair的第一个元素为待排序元素,第二个元素为该元素的重复个数,用以确定该算法是否稳定。

 1 void counting_sort(vector<pair<int, int> > &array, int k) {
 2     vector<int> array_count(k, 0);
 3     for (vector<pair<int, int> >::const_iterator iter = array.begin(); iter != array.end(); ++iter)
 4         ++array_count[iter->first];
 5     for (size_t i = 1; i != array_count.size(); ++i)
 6         array_count[i] += array_count[i-1];
 7 
 8     for (int i = array.size() -1; i != 0; --i) {
 9         int j = array_count[array[i].first] - 1;
10         if (j != i) {
11             while (j >= 0 && j != i && array[j].first == array[i].first) --j;
12             if (j != i) {
13                 if (j == -1) j = 0;
14                 pair<int, int> temp = array[i];
15                 array[i] = array[j];
16                 array[j] = temp;
17                 ++i;
18             }
19         }
20     }
21 }

 

 

posted @ 2012-11-14 12:45  zzwab  阅读(1183)  评论(0编辑  收藏  举报