sgi stl中list的sort函数实现

sgi stl中list的sort()函数内容如下:

// list 不能使用STL 算法 sort(),必须使用自己的 sort() member function,
// 因为STL算法sort() 只接受RamdonAccessIterator.
// 本函式采用 quick sort.
template <class T, class Alloc>
void list<T, Alloc>::sort() {
// 以下判断,如果是空白串行,或仅有一个元素,就不做任何动作。
if (node->next == node || link_type(node->next)->next == node) return;

// 一些新的 lists,做为中介数据存放区
list<T, Alloc> carry;
list<T, Alloc> counter[64];
int fill = 0;
while (!empty()) {
carry.splice(carry.begin(), *this, begin()); //取出list中的一个数据,存入carry
int i = 0;
while(i < fill && !counter[i].empty()) {
counter[i].merge(carry); //将carry中的数据,和 counter[i]链中原有数据合并
carry.swap(counter[i++]); //交换carry 和counter[i] 数据
}
carry.swap(counter[i]); 
if (i == fill) ++fill;
}

for (int i = 1; i < fill; ++i) // sort之后,善后处理,把数据统一起来
counter[i].merge(counter[i-1]);
swap(counter[fill-1]);
}


详细道来:
fill ------> 2^fill 表示现在能处理的数据的最大数目
counter[ fill ]---> 将处理完的2^fill个数据存入 counter[ fill ]中
carry---> 就像一个临时中转站, 在处理的数据不足 2 ^ fil l时,在counter[ i ] ( 0=<i<fill)之间移动数据(改变指针)

步骤如下:
1) 读入一个数据(carry.splice),通过 carry 将数据存入 counter[0] 中;
随后处理下一个数据, carry 保存数据
a. counter[0].merge(carry) , 此时 counter[0] 容纳的数据个数 > 2^0
b. 将counter[0]链中的数据,通过carry,转移到counter[1]链,.... 直至处理的数据个数达到 2 ^ fill

2) fill++ , 重复 1) 至处理完所有的数据。


非递归的快速排序实现方式,很巧妙!!!
counter 数组为64 --- 所以此算法,一次最多能处理 2 ^ 64 -2 个数据

比如我们的list里有如下几个需要排序的元素:21,45,1,30,52,3,58,47,22,59,0,58。

排序的时候怎么做,我们先定义若干中转list在上述代码中定义了64个元素的数组

list<_Tp, _Alloc> __counter[64]; 其中里边存什么呢?他们都是用来中转用的

__counter[0]里存放2(0+1)次方个元素
__counter[1]里存放2(1+1)次方个元素
__counter[2]里存放2(2+1)次方个元素
__counter[3]里存放2(3+1)次方个元素,依次类推

那又是怎么个存放方法呢?一个指导原则就是当第i个元素即__counter[i]的内容个数等于2(i+1)次方时,就要把__counter[i]的数据转移给__count[i+1]。

具体过程如下:

取出第1个数21,放到__counter[0]里,这时__counter[0]里有一个元素,小于2,继续

__counter[0]: 21

__counter[1]: NULL

取出第2个数45,放到__counter[0]里(不是简单的放,而是排序放,类似两个list做merge),这时__counter[0]里有2个元素了,需要把这两个元素转移到__counter[1].

__counter[0]: NULL

__counter[1]: 21,45

取出第3个数1,放到__counter[0]里,__count[0]与__count[1]都小于规定个数

__counter[0]: 1

__counter[1]: 21,45

取出第4个数30,放到__counter[0]里,这时__counter[0]的个数等于2了,需要转移到__counter[1]里

__counter[0]: NULL

__counter[1]: 1,21,30,45

但这时__counter[1]里的个数又等于4了,所有需要把__counter[1]的值转移到__counter[2]里,

__counter[0]: NULL

__counter[1]: NULL

__counter[2]: 1,21,30,45

然后取出52,放入__counter[0]

__counter[0]: 52

__counter[1]: NULL

__counter[2]: 1,21,30,45

然后取出3,放入__counter[0]

__counter[0]: 3,52

__counter[1]: NULL

__counter[2]: 1,21,30,45

这时候需要转移

__counter[0]: NULL

__counter[1]: 3,52

__counter[2]: 1,21,30,45

然后取58

__counter[0]: 58

__counter[1]: 3,52

__counter[2]: 1,21,30,45

然后取47

__counter[0]: 47,58

__counter[1]: 3,52

__counter[2]: 1,21,30,45

需要转移

__counter[0]: NULL

__counter[1]: 3,47,52,58

__counter[2]: 1,21,30,45

还需要转移

__counter[0]: NULL

__counter[1]: NULL

__counter[2]: 1,3,21,30,47,45,52,58

还需要转移

__counter[0]: NULL

__counter[1]: NULL

__counter[2]: NULL

__counter[3]: 1,3,21,30,47,45,52,58

然后再取59

__counter[0]: 59

__counter[1]: NULL

__counter[2]: NULL

__counter[3]: 1,3,21,30,47,45,52,58

然后取0

__counter[0]: 0,59

__counter[1]: NULL

__counter[2]: NULL

__counter[3]: 1,3,21,30,47,45,52,58

需要转移

__counter[0]: NULL

__counter[1]: 0,59

__counter[2]: NULL

__counter[3]: 1,3,21,30,47,45,52,58

最后取58

__counter[0]: 58

__counter[1]: 0,59

__counter[2]: NULL

__counter[3]: 1,3,21,30,47,45,52,58

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值