list::sort源码剖析

一:用法示例

函数原型:

有两个重载。

(1)void sort();

(2)template <class Compare>
              void sort (Compare comp);

实现功能:对链表进行排序,默认是升序,如自定义是降序,需使用重载类型第二个,具体操作看下面的示例。


示例:

// list::sort
#include <iostream>
#include <list>
#include <string>
#include <cctype>

// comparison, not case sensitive.
bool compare_nocase(const std::string& first, const std::string& second)
{
	unsigned int i = 0;
	while ((i < first.length()) && (i < second.length()))
	{
		if (tolower(first[i]) < tolower(second[i])) return true;
		else if (tolower(first[i]) > tolower(second[i])) return false;
		++i;
	}
	return (first.length() < second.length());
}

int main()
{
	std::list<std::string> mylist;
	std::list<std::string>::iterator it;
	mylist.push_back("one");
	mylist.push_back("two");
	mylist.push_back("Three");

	mylist.sort();

	std::cout << "mylist contains:";
	for (it = mylist.begin(); it != mylist.end(); ++it)
		std::cout << ' ' << *it;
	std::cout << '\n';

	mylist.sort(compare_nocase);

	std::cout << "mylist contains:";
	for (it = mylist.begin(); it != mylist.end(); ++it)
		std::cout << ' ' << *it;
	std::cout << '\n';

	return 0;
}

Output:

mylist contains: Three one two
mylist contains: one Three two


二:源码

template <class _Tp, class _Alloc>
void list<_Tp, _Alloc>::sort()
{
	if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node)
	{
		list<_Tp, _Alloc> __carry;
		list<_Tp, _Alloc> __counter[64];
		int __fill = 0;
		while (!empty())
		{
			__carry.splice(__carry.begin(), *this, begin());
			int __i = 0;
			while (__i < __fill && !__counter[__i].empty())
			{
				__counter[__i].merge(__carry);
											 
				__carry.swap(__counter[__i++]);
			}
			__carry.swap(__counter[__i]);       								 
			if (__i == __fill) ++__fill;
		}
		for (int __i = 1; __i < __fill; ++__i)
			__counter[__i].merge(__counter[__i - 1]);
		swap(__counter[__fill - 1]);
	}
}


三:源码剖析

template <class _Tp, class _Alloc>
void list<_Tp, _Alloc>::sort()
{
	//链表长度如果是0或者1,直接结束。这里没有使用size()是因为速度相对源码的这样设计会慢。
	if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node)
	{
		list<_Tp, _Alloc> __carry;
		list<_Tp, _Alloc> __counter[64];
		int __fill = 0;
		/*
		定义了一个类似于搬运作用的链表carry和具有中转站作用的链表counter,这里首先对counter[i]里面
		存储数据的规则进行分析;counter[i]里面最多存储数据个数为2^(i+1),若存储数据超过该数字,则向相邻高位
		进位,即把counter[i]链表里的内容都合并到counter[i+1]链表。carry负责取出原始链表的头一个数据
		节点和交换数据中转站作用;源码中的fill表示当前可处理数据的个数为2^fill.那么counter数组长度64,
		也就是排序元素个数最多可到2^64-1,这数据量已经足够。
		*/

		while (!empty())
		{
			__carry.splice(__carry.begin(), *this, begin());//把当前链表的第一个节点放在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]);//交换链表carry和counter[i]内容
			if (__i == __fill) ++__fill;
		}
		for (int __i = 1; __i < __fill; ++__i)
			__counter[__i].merge(__counter[__i - 1]);//把低位不满足进位的剩余数据全部有序的合并到上一位
		swap(__counter[__fill - 1]);//最后把已排序好的链表内容交换到当前链表
	}
}

建议读者在阅读一些算法代码,尤其是经典的源代码时,如果在理解上有困难,一定要自己设计测试数据,然后再纸上模拟算法流程,由此加深理解。




点击进入目录----> C++源码剖析目录







  


 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值