關於C++使用位域進行數據排序的總結

今天看了《編程珠璣》第二版的第一章,感覺使用位域進行數據排序挺有意思的,於是用C++寫了一下簡單的位域排序,現在來寫寫總結。

首先這篇文章的主題是簡單的位域排序,也就是說需要滿足以下的條件:

1.需要排序的數據集中不存在重複的數據;

2.對排序程序所使用的內存沒有限制。

條件限制好了,然後就可以來寫代碼了,下面的代碼均在VS2017上編寫,電腦配置爲i5-6200u + 8G ddr3 1600Mhz內存 +  SATA SSD。

首先是生成需要排序的隨機數據集的代碼(生成一百萬個小於一千萬的不重複的正整數),如下所示

#include <set>
#include <random>
#include <fstream>
#include <ctime>
#include <vector>

int main()
{
	std::default_random_engine dre(std::time(nullptr));
	std::uniform_int_distribution<unsigned> uid(1, 10000000);
	std::ofstream output_file("D:/1.txt");
	std::vector<unsigned> vec_random_data;
	std::set<unsigned> set_random_data;

	unsigned random_data = 0;

	for (size_t index = 0; index < 10000000; ++index)
	{
		set_random_data.insert(uid(dre));
		if (set_random_data.size() >= 1000000)
		{
			break;
		}
	}

	vec_random_data.assign(set_random_data.cbegin(), set_random_data.cend());
	set_random_data.clear();
	std::random_shuffle(vec_random_data.begin(), vec_random_data.end());
	for (auto data : vec_random_data)
	{
		output_file << data << "\n";
	}
	output_file.close();

	return 0;
}

然後是使用一般的排序方法的代碼,將需要排序的文件中的數據讀入內存,排序,輸出,如下所示

#include <fstream>
#include <set>
#include <chrono>
#include <iostream>

int main()
{
	unsigned sort_data = 0;
	std::ifstream input_file("D:/1.txt");
	std::set<unsigned> set_sort_data;
	auto begin_time = std::chrono::steady_clock::now();

	//用時3272ms,使用34MB內存
	while (input_file >> sort_data)
	{
		set_sort_data.insert(sort_data);
	}
	input_file.close();

	std::ofstream output_file("D:/2.txt");
	for (auto data : set_sort_data)
	{
		output_file << data << "\n";
	}
	output_file.close();

	std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - begin_time).count() << "ms" << std::endl;

	return 0;
}

可以看到一般的排序方法(Release模式下)在我的電腦上面所使用的內存爲34MB,花費時間爲3272ms。

最後我們來看看使用位域排序的代碼,步驟爲創建位域-按照文件中的值來設置位域中的位-按照位域中的位輸出排序後的數據,如下所示

#include <fstream>
#include <chrono>
#include <iostream>
#include <bitset>

int main()
{
	unsigned sort_data = 0;
	std::ifstream input_file("D:/1.txt");
	std::set<unsigned> set_sort_data;
	auto begin_time = std::chrono::steady_clock::now();

	//用時2633ms,使用2MB內存
	std::bitset<10000000> bitset_sort_data;
	while (input_file >> sort_data)
	{
		bitset_sort_data[sort_data] = 1;
	}
	input_file.close();

	std::ofstream output_file("D:/2.txt");
	for (unsigned index = 0; index < bitset_sort_data.size(); ++index)
	{
		if (bitset_sort_data[index] == 1)
		{
			output_file << index << "\n";
		}
	}
	output_file.close();

	std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - begin_time).count() << "ms" << std::endl;

	return 0;
}

可以看到位域排序的方法(Release模式下)在我的電腦上面帶來了驚人的性能提升,所使用的內存爲2MB,花費時間爲2633ms。

以上就是我對位域排序的總結,可以看到雖然位域排序有條件限制,但是所帶來的性能提升卻是令人驚喜的。

PS:上面所寫的位域排序代碼中,因爲

std::bitset<10000000> bitset_sort_data;

佔用了2MB的棧空間,但是VS2017項目默認棧空間爲1MB,所以會導致棧溢出、程序運行失敗的問題,解決的辦法爲增加VS2017項目的棧空間,詳細可查看這個博客https://blog.csdn.net/wwkaven/article/details/40713961

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章