線性時間排序C++代碼集合(計數排序,基數排序,桶排序([0~1)的浮點數))



1. 計數排序

輸入:待排序數組 vec

輸出:排序結果數組 res

佔用額外空間:max_value(vec) 大小的數組

void countSort(vector<int> & vec,vector<int> & result)
{
	vector<int> c_vec;
	result.resize(vec.size());
	for (auto val : vec)
	{
		if (c_vec.size() <= val + 1)           //範圍爲0~n的數據,共有 n + 1 種取值,包含0
			c_vec.resize(val + 1,0);
		c_vec[val] += 1;
	}

	//adjust c_vec
	for (int i = 1; i != c_vec.size(); ++i)
		c_vec[i] += c_vec[i - 1];

	//adjust
	for (auto val : vec)          //此時從後往前遍歷 vec 並放入元素,則計數排序的結果是穩定的。按照當前寫法不穩定
	{
		result[c_vec[val]-1] = val;   //當前排名爲n 的數據,在vec 中的下標爲[n-1],下標從0開始
		--c_vec[val];
	}
}


2.基數排序

輸入:待排序數組

void radixSort(vector<int>& vec)
{
	vector<int> tmp(vec.size(), 0);
	vector<int> bucket(10, 0);   //桶中存放 0 ~ 9

	int max_num = INT_MIN;		//用來統計最高位,用於終止循環
	std::for_each(vec.begin(), vec.end(), [&max_num](int i)mutable{if (i > max_num) max_num = i; });

	int bits_count = 1;
	
	while ((max_num / bits_count))
	{
		//獲取位數
		for (auto val : vec)
			bucket[(val / bits_count) % 10] += 1;
		//統計排序
		for (size_t i = 1; i != bucket.size(); ++i)
			bucket[i] += bucket[i - 1];
		
		//根據統計的排序值,將值放入臨時存儲區。**特別注意此處必須從後往前找數據,因爲根據計數的原理,桶中的排序是從後往前的
		for (auto iter = vec.rbegin(); iter != vec.rend(); ++iter)
		{
			int val = *iter;
			tmp[bucket[(val / bits_count) % 10] - 1] = val;
			--bucket[(val / bits_count) % 10];
		}
		//將臨時存儲區的值轉回原存儲
		for (size_t i = 0; i != tmp.size(); ++i)
			vec[i] = tmp[i];

		//清空桶
		for (auto & val : bucket)
			val = 0;
			

		//累計當前值
		bits_count *= 10;
	}
}

3.桶排序

輸入:在[0~1)均勻分佈的浮點數

穩定性:穩定

struct Node
{
	double fval;
	shared_ptr<Node>  next;
	shared_ptr<Node>  prev;

	Node(float f) :fval(f), next(nullptr), prev(nullptr){}
};


//對 [0,1) 內均勻分佈的小數進行排序
void bucketSort(vector<double> &vec)
{
	map<int, shared_ptr<Node>> bucket;	//桶,每個桶中放了一個鏈表,鏈表中的元素使用插入排序
	
	for (auto fval : vec)
	{
		int bits = static_cast<int>(fval * 10) % 10;    //取出小數點後第一位
		
		shared_ptr<Node> point(new Node(fval));			//構造新節點,用智能指針控制堆內存的釋放

		shared_ptr<Node> root = bucket[bits];			//取出當前桶的根節點

		if (root == NULL)								//空桶,放入第一個元素即可
		{
			bucket[bits] = point;
			continue;
		}

		shared_ptr<Node> prev = NULL,curr = root;		//開始插入排序

		while (curr != NULL)
		{
			if (curr->fval <= fval)  //迭代器向後移動	備註:使用小於等於保持穩定性
			{
				prev = curr;		
				curr = curr->next;
			}
			else
				break;
		}


		point->prev = prev;			//將當前結點接入鏈表
		point->next = curr;
		if (prev != NULL)			//頭節點爲空,則當前節點應該爲桶中的根節點
			prev->next = point;
		else
			bucket[bits] = point;	//替換掉根節點
		if (curr != NULL)
			curr->prev = point;		//接入鏈表中
	}

	size_t index = 0;
	for (auto iter = bucket.begin(); iter != bucket.end(); ++iter)  //map 按關鍵字 0 ~ 9 自動排序,即是取出按桶的順序取出
	{
		shared_ptr<Node> root = iter->second;
		while (root != NULL)
		{
			vec[index++] = root->fval;   //獲取值
			root = root->next;
		}
	}
}



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