• 常见排序算法


    常见排序算法

    编写代码并测试了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;
    }
    
  • 相关阅读:
    使用homebrew安装mysql
    MacOS下命令行安装神器brew
    mac Navicat 破解+汉化(亲测可用)
    eos开发(三)使用cleos命令行客户端操作EOS——关于钱包wallet和账户account
    eos开发(二)使用cleos命令行客户端操作EOS(钱包wallet基础操作)
    php职业规划
    temp
    事业随想
    系统时间错误
    加解密,token
  • 原文地址:https://www.cnblogs.com/virgildevil/p/12520994.html
Copyright © 2020-2023  润新知