常见排序算法

常见排序算法

编写代码并测试了5种排序算法

有冒泡排序,选择排序,插入排序,堆排序,归并排序.

下面也给出了代码在机器上的运行结果,虽然不同机器结果会不一样,但是仍然能够比较直观地感受到这些算法的区别,以及理论与实现之间的差距.

// sort.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include <vector>
#include <limits.h>
#include <time.h>
#include <string>
#include <stack>
#include <algorithm>

using namespace std;

//计时类,调用End将返回经历的秒数
class Timer {
private:
	clock_t start;
	clock_t finish;
	double duration;
public:
	Timer() {
		start = 0;
		finish = 0;
	};
	void Start() {
		start = clock();
	}
	double End() {
		finish = clock();
		duration = (double)(finish - start) / CLOCKS_PER_SEC;
		start = 0;
		finish = 0;
		return duration;
	}
};



//时间复杂度 平均O(n^2) 最坏(n^2) 最好O(n)
//空间复杂度 O(1)
//稳定性 稳定
namespace bubble_sort {
	void sort(vector<int>& v)
	{
		if (v.size() == 0)return;
		for (int j = 0; j < v.size(); j++)
		{
			for (int i = 0; i < v.size() - 1; i++)
			{
				if (v[i] > v[j])
				{
					//swap(i,j)
					int tmp = v[j];
					v[j] = v[i];
					v[i] = tmp;
				}
			}
		}


	}
}

//时间复杂度 平均O(n^2) 最坏(n^2) 最好O(n^2)
//空间复杂度 O(1)
//稳定性 不稳定
namespace select_sort {
	void sort(vector<int>& v)
	{
		if (v.size() == 0)return;
		for (int j = 0; j < v.size(); j++)
		{
			int min_pos = j;
			for (int i = j; i < v.size(); i++)
			{
				if (v[i] < v[min_pos]) {
					min_pos = i;
				}
			}
			//swap(j,min_pos)
			int tmp = v[min_pos];
			v[min_pos] = v[j];
			v[j] = tmp;
		}
	}
}


//时间复杂度 平均O(n^2) 最坏(n^2) 最好O(n)
//空间复杂度 O(1)
//稳定性 稳定
namespace insert_sort {
	void sort(vector<int>& v)
	{
		if (v.size() == 0)return;
		for (int j = 1; j < v.size(); j++)
		{
			int i = j;
			while (i >= 1 && v[i] < v[i - 1])
			{
				//swap(i,i-1)
				int tmp = v[i - 1];
				v[i - 1] = v[i];
				v[i] = tmp;
				i--;
			}
		}
	}
}


namespace heap_sort_recur {

	struct Node {
		int val;
		Node* lchild;
		Node* rchild;
	};

	Node* head;
	int m_i = 0;
	vector<int> m_v;

	void re_build_heap(Node *node, Node *last_node, int val) {
		if (node == NULL) {
			Node* new_node = new Node;
			new_node->val = val;
			new_node->lchild = NULL;
			new_node->rchild = NULL;

			if (last_node->val > val) {
				last_node->lchild = new_node;
			}
			if (last_node->val <= val) {
				last_node->rchild = new_node;
			}
			return;
		}

		if (val < node->val)
		{
			re_build_heap(node->lchild, node, val);
		}
		if (val >= node->val)
		{
			re_build_heap(node->rchild, node, val);
		}

	}

	//中序遍历写回vector
	void re_write_back(Node* node)
	{
		if (node->lchild != NULL) {
			re_write_back(node->lchild);
		}
		if (node != NULL)
		{
			m_v[m_i] = node->val;
			m_i++;
		}
		if (node->rchild != NULL) {
			re_write_back(node->rchild);
		}
	}

	void sort(vector<int>& v)
	{
		if (v.size() == 0)return;
		m_v = v;
		head = new Node;
		head->lchild = NULL;
		head->rchild = NULL;
		head->val = m_v[0];
		for (int i = 1; i < m_v.size(); i++)
		{
			re_build_heap(head, head, m_v[i]);
		}
		re_write_back(head);
		for (int i = 0; i < v.size(); i++)
		{
			v[i] = m_v[i];
		}
	}
}

namespace heap_sort_arr {
	vector<int> arr;

	void sort(vector<int>& v)
	{
		/*Build Heap*/
		int k = 2;
		for (int i = 0; i < v.size(); i++)
		{
			k *= 2;
		}
		k--;

		arr.resize(k,-1);  // 存储树的数组,2^n - 1个元素 ,  -1  表示无数据
		arr[0] = v[0];
		for (int i = 1; i < v.size(); i++) {
			int j = 0;
			while (arr[j] != -1)
			{
				int left = 2 * j + 1;
				int right = 2 * j + 2;

				if (v[i] < arr[j]) {
					j = left;
				}
				else {
					j = right;
				}
			}
			arr[j] = v[i];
		}
		
		stack<int> s;
		int ii = 0;
		int now = 0;
		do {
			while (arr[now] != -1) {
				s.push(now);
				now = 2 * now + 1;
			}
			now = s.top();
			v[ii] = arr[now];
			s.pop();
			ii++;
			now = 2 * now + 2;
		} while (s.size() != 0 || arr[now] != -1);

		return;
	}

}

//时间复杂度 平均O(nlog2n) 最坏(nlog2n) 最好O(nlog2n)
//空间复杂度 O(1)
//稳定性 不稳定
namespace heap_sort_node {
	struct Node {
		int val;
		Node* lchild;
		Node* rchild;
	};

	//Test for print heap
	void recur_mid(Node* node) {
		if (node == NULL)return;
		recur_mid(node->lchild);
		cout << node->val << " ";
		recur_mid(node->rchild);

	}

	void sort(vector<int>& v)
	{
		/*Build Heap*/
		Node* head;
		head = new Node;
		head->val = v[0];
		head->lchild = NULL;
		head->rchild = NULL;

		Node* node;
		Node* last_node;
		for (int i = 1; i < v.size(); i++) {
			node = head;
			last_node = head;
			while (node != NULL)
			{
				if (v[i] < node->val) {
					last_node = node;
					node = node->lchild;
				}
				else {
					last_node = node;
					node = node->rchild;
				}
			}

			Node* new_node = new Node;
			new_node->val = v[i];
			new_node->lchild = NULL;
			new_node->rchild = NULL;

			if (v[i] < last_node->val) {
				last_node->lchild = new_node;
			}
			else {
				last_node->rchild = new_node;
			}

		}

		//Test for print heap
		//recur_mid(head);
		//cout << endl;

		//Use loop for inorder traversal to avoid stack overflow
		stack<Node*> s;
		int ii = 0;
		node = head;
		do {
			while (node != NULL) {
				s.push(node);
				node = node->lchild;
			}

			node = s.top();
			v[ii] = node->val;
			s.pop();
			ii++;
			node = node->rchild;
		} while (s.size() != 0 || node != NULL);

	}

}

//时间复杂度 平均O(nlog2n) 最坏(nlog2n) 最好O(nlog2n)
//空间复杂度 O(n)
//稳定性 稳定
namespace merge_sort {

	struct Interval {
		int left;
		int right;
		int state;	//记录着递归调用时的步骤
	};

	void sort(vector<int>& v)
	{
		int left = 0;
		int right = v.size() - 1;
		int mid = (right + left) / 2;

		Interval _inter;
		_inter.left = left;
		_inter.right = right;
		_inter.state = 0;

		//Convert recursion to loop
		/*
		recur(left,right)
		{
			if(left>=right)return;
			recur(left,mid);
			recur(mid+1,right);
			merge();
		}
		*/

		stack<struct Interval> s;

		s.push(_inter);
		while (s.size() != 0)
		{
			Interval interval = s.top();
			s.pop();
			
			left = interval.left;
			right = interval.right;
			mid = (left + right) / 2;

			if (interval.state == 0) {
				if (left >= right) {
					interval.state = 3;				//3  表示不处理这种情况
					s.push(interval);
					continue;
				}

				interval.state = 1;
				s.push(interval);

				Interval inter1;
				inter1.left = left;
				inter1.right = mid;
				inter1.state = 0;
				s.push(inter1);

			}
			else if (interval.state == 1) {
				interval.state = 2;
				s.push(interval);

				Interval inter1;
				inter1.left = mid+1;
				inter1.right = right;
				inter1.state = 0;
				s.push(inter1);
			}
			else if (interval.state == 2) {
				vector<int> vec; //Storage sorted data
				int i = left;
				int j = mid + 1;
				while (i <= mid || j <= right) {
					//If one out of the limit, the other case is executed
					if (j > right) {
						vec.push_back(v[i]);
						i++;
						continue;
					}
					else if (i > mid) {
						vec.push_back(v[j]);
						j++;
						continue;
					}

					//Keep the sort stable
					if (v[i] <= v[j]) {
						vec.push_back(v[i]);
						i++;
					}
					else if (v[i] > v[j]) {
						vec.push_back(v[j]);
						j++;
					}
				}

				//Copy sorted data to v
				for (int i = 0; i < vec.size(); i++)
				{
					v[left + i] = vec[i];
				}

			}

		}

	}
}


enum DATA_TYPE {
	RANDOM,
	INC,
	DEC
};

class TestCase {
	Timer timer;
	vector<int> v;
	vector<int> ch_vec;
public:
	/*
	size:样例的个数
	dtype:生成样例的方式
	_sort:排序时调用的方法
	print_data:是否打印排序前数据和排序后数据
	check:是否进行错误检查
	*/
	TestCase(int size, DATA_TYPE dtype, void(*_sort)(vector<int>&), bool print_data = false,bool check = false) {
		init_vec(size, dtype);
		
		//Sorting original data
		if (check) {
			ch_vec = v;
			std::sort(ch_vec.begin(), ch_vec.end());
		}

		//Unsorted data
		if (print_data) {
			print_vec();
		}

		//Sorting with provided method
		timer.Start();
		_sort(v);
		double duration = timer.End();
		cout << "cost time: " << duration << " seconds" << endl;
		
		//Sorted data
		if (print_data) {
			print_vec();
		}

		bool error = false;
		if (check) {
			for (int i = 0; i < v.size(); i++) {
				if (v[i] != ch_vec[i]) {
					error = true;
					break;
				}
			}
		}

		if (error) {
			cout << "incorrect result" << endl;
		}
		else {
			cout << "corret result" << endl;
		}

	}

	void print_vec()
	{
		if (v.size() == 0)return;
		for (int i = 0; i < v.size(); i++)
		{
			cout << v[i] << " ";
		}
		cout << endl;
	}
private:
	void init_vec(int size, DATA_TYPE dtype) {
		v.resize(size);
		switch (dtype) {
		case INC:
			for (int i = 0; i < size; i++)
			{
				v[i] = i;
			}
			break;
		case DEC:
			for (int i = 0; i < size; i++)
			{
				v[i] = size - i;
			}
			break;
		case RANDOM:
			srand(time(0));
			for (int i = 0; i < size; i++)
			{
				v[i] = rand()%9999;				//Make it smaller
				//v[i] = rand();						

			}
			break;
		default:
			break;
		}
	}
};

int main() {
	const int SIZE = 30000;
	//TestCase testCase1(SIZE,RANDOM,bubble_sort::sort);						//SIZE=2000,	3.4s
	//TestCase testCase2(SIZE,RANDOM,select_sort::sort);						//SIZE=2000,	1.2s
	//TestCase testCase3(SIZE,RANDOM,insert_sort::sort);						//SIZE=2000,	1.3s
	//TestCase testCase4(SIZE, RANDOM, heap_sort_recur::sort);					//SIZE=80000,	0.2s  然而SIZE = 100000的时候,malloc failure: Stack overflow    
	//TestCase testCase5(SIZE, RANDOM, heap_sort_arr::sort);					//SIZE=23,		2.0s  由于使用数组存储树,空间利用率低下,特别是当树结构恶化的时候vector将无法申请到足够的内存
	//TestCase testCase6(SIZE, RANDOM, heap_sort_node::sort,false,true);		//SIZE=100000,	1.0s  最快的一个
	//TestCase testCase7(SIZE, RANDOM, merge_sort::sort, false, true);			//SIZE=30000,	2.0S  时间主要花在了临时数据的拷贝,存储和释放上面

	return 0;
}
posted @ 2020-03-18 22:44  virgil_devil  阅读(166)  评论(0编辑  收藏  举报