排序算法練習

#include <iostream>
#include <iterator>
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <cassert>


std::vector<int> generateIntList(int size = 10)
{
	std::vector<int> result_list;
	std::generate_n(
		std::back_insert_iterator<std::vector<int>>(result_list),
		size,
		[]() { return std::rand() % 10; }
	);
	return std::move(result_list);
}

void showIntList(const std::vector<int>& ll)
{
	//std::cout << "list: ";
	std::copy(ll.begin(), ll.end(), std::ostream_iterator<int>(std::cout, " "));
	std::cout << "\n";
}


//插入排序
//每次遍歷保證p位置的元素,比p左邊的元素小
void insertSort(std::vector<int>& ll)
{
	for (decltype(ll.size()) p = 1; p < ll.size(); ++p)
	{
		auto tmp = ll[p];
		auto j = p;
		for (; j > 0 && tmp < ll[j - 1]; --j)
		{
			ll[j] = ll[j - 1];
		}
		ll[j] = tmp;
	}
}


void insertSort(std::vector<int>& ll, int left, int right)
{
	for (decltype(ll.size()) p = left + 1; p <= right; ++p)
	{
		auto tmp = ll[p];
		auto j = p;
		for (; j > left && tmp < ll[j - 1]; --j)
		{
			ll[j] = ll[j - 1];
		}
		ll[j] = tmp;
	}
}


//謝爾排序
//帶增量的插入排序。。。
void shellSort(std::vector<int>& ll)
{
	for (auto gap = ll.size() / 2; gap > 0; gap /= 2)
	{
		for (auto p = gap; p < ll.size(); p++)
		{
			auto tmp = ll[p];
			auto j = p;
			for (; j >= gap && tmp < ll[j - gap]; j -= gap)
			{
				ll[j] = ll[j - gap];
			}
			ll[j] = tmp;
		}
	}
}


//堆排序
//先創建二叉大頂堆,交換堆頂元素和最後一個元素
//二叉堆的性質:位置在i的元素,左兒子在2i,右兒子在2i+1


//將位置i的元素下濾到指定的層數, 每次都是與左右兩個兒子中的較大值進行交換, 大於兩個兒子時中止下濾
void percDown(std::vector<int>& ll, int i, int n)
{
	auto leftChild = [](const int i) -> int {return 2 * i + 1; };

	int child;
	auto tmp = ll[i];
	for (; leftChild(i) < n; i = child)
	{
		child = leftChild(i);
		if (child != n - 1 && ll[child] < ll[child + 1])
		{
			++child;
		}

		if (tmp < ll[child])
		{
			ll[i] = ll[child];
		}
		else
		{
			break;
		}
	}
	ll[i] = tmp;
}

void heapSort(std::vector<int>& ll)
{
	//從下往上進行下濾操做,創建一個大頂堆
	for (int i = ll.size() / 2; i >= 0; --i)
	{
		percDown(ll, i, ll.size());
	}

	for (int j = ll.size() - 1; j > 0; --j)
	{
		std::swap(ll[0], ll[j]);//交換堆頂元素和最後一個元素
		percDown(ll, 0, j);//對堆頂進行下濾操做
	}
}


//歸併排序
void merg(std::vector<int>& ll, std::vector<int>& tmpArray, int leftPos, int rightPos, int rightEnd)
{
	auto leftEnd = rightPos - 1;
	auto tmpPos = leftPos;
	auto numElements = rightEnd - leftPos + 1;

	while (leftPos <= leftEnd && rightPos <= rightEnd)
	{
		if (ll[leftPos] <= ll[rightPos])
		{
			tmpArray[tmpPos++] = ll[leftPos++];
		}
		else
		{
			tmpArray[tmpPos++] = ll[rightPos++];
		}
	}

	while (leftPos <= leftEnd)
	{
		tmpArray[tmpPos++] = ll[leftPos++];
	}

	while (rightPos <= rightEnd)
	{
		tmpArray[tmpPos++] = ll[rightPos++];
	}

	for (auto i = 0; i < numElements; i++, rightEnd--)
	{
		ll[rightEnd] = tmpArray[rightEnd];
	}
}

//分治策略, 數組切成兩半,而後對兩個數組進行排序以後, 而後再合併
void mergSortDriver(std::vector<int>& ll, std::vector<int>& tmpArray, int left, int right)
{
	if (left < right)
	{
		auto center = (left + right) / 2;
		mergSortDriver(ll, tmpArray, left, center);
		mergSortDriver(ll, tmpArray, center + 1, right);
		merg(ll, tmpArray, left, center + 1, right);
	}
}


void mergSort(std::vector<int>& ll)
{
	std::vector<int> tmpArray(ll.size());
	mergSortDriver(ll, tmpArray, 0, ll.size() - 1);
}



//快速排序
//選擇一個樞紐元, 而後確保左邊的元素小於樞紐元, 右邊的元素大於樞紐元, 而後分別對左右兩邊分別進行快排
int median3(std::vector<int>& a, int left, int right)
{
	auto center = (left + right) / 2;
	if (a[center] < a[left])
	{
		std::swap(a[left], a[center]);
	}
	if (a[right] < a[left])
	{
		std::swap(a[left], a[right]);
	}
	if (a[right]<a[center])
	{
		std::swap(a[center], a[right]);
	}

	std::swap(a[center], a[right - 1]);
	return a[right - 1];
}

void quickSort(std::vector<int>& ll, int left, int right)
{
	if (left + 10 <= right)
	{
		auto pivot = median3(ll, left, right);

		auto i = left, j = right - 1;
		while (true)
		{
			while (ll[++i] < pivot) {}
			while (pivot < ll[--j]) {}
			if (i<j)
			{
				std::swap(ll[i], ll[j]);
			}
			else
			{
				break;
			}
		}

		std::swap(ll[i], ll[right - 1]);
		quickSort(ll, left, i - 1);
		quickSort(ll, i + 1, right);
	}
	else
	{
		insertSort(ll, left, right);
	}

}


void sort_test()
{
	if (true)
	{
		auto l1 = generateIntList();
		auto l2 = l1;
		std::cout << "insertSort>>>>" << '\n';
		std::cout << "before: ";
		showIntList(l1);

		insertSort(l1);
		std::cout << "l1: ";
		showIntList(l1);

		std::sort(l2.begin(), l2.end());
		std::cout << "l2: ";
		showIntList(l2);

		//用標準庫的sort函數的結果來進行測試驗證
		assert(l1 == l2);
	}

	if (true)
	{
		auto l1 = generateIntList();
		auto l2 = l1;
		std::cout << "shellSort>>>>" << '\n';
		std::cout << "before: ";
		showIntList(l1);

		shellSort(l1);
		std::cout << "l1: ";
		showIntList(l1);

		std::sort(l2.begin(), l2.end());
		std::cout << "l2: ";
		showIntList(l2);

		//用標準庫的sort函數的結果來進行測試驗證
		assert(l1 == l2);
	}

	if (true)
	{
		auto l1 = generateIntList();
		auto l2 = l1;
		std::cout << "heapSort>>>>" << '\n';
		std::cout << "before: ";
		showIntList(l1);

		heapSort(l1);
		std::cout << "l1: ";
		showIntList(l1);

		std::sort(l2.begin(), l2.end());
		std::cout << "l2: ";
		showIntList(l2);

		//用標準庫的sort函數的結果來進行測試驗證
		assert(l1 == l2);
	}


	if (true)
	{
		auto l1 = generateIntList();
		auto l2 = l1;
		std::cout << "mergSort>>>>" << '\n';
		std::cout << "before: ";
		showIntList(l1);

		mergSort(l1);
		std::cout << "l1: ";
		showIntList(l1);

		std::sort(l2.begin(), l2.end());
		std::cout << "l2: ";
		showIntList(l2);

		//用標準庫的sort函數的結果來進行測試驗證
		assert(l1 == l2);
	}

	if (true)
	{
		auto l1 = generateIntList(30);
		auto l2 = l1;
		std::cout << "quickSort>>>>" << '\n';
		std::cout << "before: ";
		showIntList(l1);

		quickSort(l1, 0, l1.size() - 1);
		std::cout << "l1: ";
		showIntList(l1);

		std::sort(l2.begin(), l2.end());
		std::cout << "l2: ";
		showIntList(l2);

		//用標準庫的sort函數的結果來進行測試驗證
		assert(l1 == l2);
	}
}
相關文章
相關標籤/搜索