各種排序及內省排序

分別寫了選擇、冒泡、插入、堆、歸併、快排的實現,以及基於快排的內省排序,並於STL的排序相比較。

//algo.h
#pragma once

int min(int x, int y)
{
	return x < y ? x : y;
}
int max(int x, int y)
{
	return x > y ? x : y;
}
void swap(int& x, int& y)
{
	int temp = x;
	x = y;
	y = temp;
}

//sort.h
#pragma once
#include<vector>
#include"algo.h"

void insertsort(std::vector<int> &vec)
{
	int m = vec.size();
	for (int i = 1; i < m; i++)
	{
		int temp = vec[i];
		int j = i - 1;
		while (j >= 0 && temp < vec[j])
		{
			vec[j + 1] = vec[j];
			j--;
		}
		vec[j+1] = temp;
	}
}

void maopao(std::vector<int> &vec)
{
	int m = vec.size();
	for (int i = 0; i < m; i++)
	{
		for (int j = 0; j < m - i - 1; j++)
		{
			if (vec[j] > vec[j + 1])
				swap(vec[j], vec[j + 1]);
		}
	}
}

void xuanze(std::vector<int> &vec)
{
	int m = vec.size();
	for (int i = 0; i < m; i++)
	{
		int index = i;
		for (int j = i; j < m; j++)
		{
			if (vec[j] < vec[index])
			{
				index = j;
			}
		}
		swap(vec[i], vec[index]);
	}
}

//heapsort.h
#pragma once
#include<vector>
#include"algo.h"

void up(std::vector<int>& vec, int i)
{
	int par = (i - 1) / 2;
	while (par && vec[i]<vec[par])
	{
		swap(vec[i], vec[par]);
		i = par;
		par = (i - 1) / 2;
	}
}
void down(std::vector<int> &vec, int i, int end)
{
	int child = i * 2 + 1;
	while (child < end)
	{
		if (child + 1 < end && vec[child] < vec[child + 1])
			child++;

		if (vec[i] < vec[child])
			swap(vec[i], vec[child]);
		else
			break;

		i = child;
		child = i * 2 + 1;
	}
}

void heapsort(std::vector<int>& vec)
{
	int m = vec.size();
	for (int i = m/2-1; i>=0; i--)
	{
		down(vec, i, m);
	}

	for (int i = m-1; i>0; i--)
	{
		swap(vec[0], vec[i]);
		down(vec, 0, i);
	}

}

//mergesort.h
#pragma once
#include<vector>
#include"algo.h"

void merge(std::vector<int> &vec, int left_beg, int right_beg, int right_end, std::vector<int> &fuzhu)
{
	int left_end = right_beg - 1;
	int i = left_beg, j = right_beg;
	int index = left_beg;
	while (i <= left_end && j <= right_end)
	{
		if (vec[i] < vec[j])
			fuzhu[index++] = vec[i++];
		else
			fuzhu[index++] = vec[j++];
	}
	while (i <= left_end)
		fuzhu[index++] = vec[i++];
	while (j <= right_end)
		fuzhu[index++] = vec[j++];

	for (int beg = left_beg; beg <= right_end; beg++)
		vec[beg] = fuzhu[beg];
}
void mergesort_recusive(std::vector<int> &vec, int beg, int end, std::vector<int> &fuzhu)
{
	if (beg < end)
	{
		int mid = beg + (end - beg) / 2;
		mergesort_recusive(vec, beg, mid, fuzhu);
		mergesort_recusive(vec, mid + 1, end, fuzhu);
		merge(vec, beg, mid+1, end, fuzhu);
	}
}
void mergesort(std::vector<int> &vec)
{
	int m = vec.size();
	std::vector<int> fuzhu(m, 0);
	mergesort_recusive(vec, 0, m - 1, fuzhu);
}

//qsort.h
#pragma once
#include<vector>
#include"algo.h"

void mid_of_three_swap(std::vector<int>& vec, int beg, int end)//頭中尾三個取中間值與尾元素交換
{
	int mid = beg + (end - beg) / 2;
	int mid_index;
	if (vec[beg] > vec[mid])
	{
		if (vec[mid] > vec[end])
		{
			swap(vec[mid], vec[end]);
			return;
		}
		else
		{
			if (vec[beg] < vec[end]) swap(vec[beg], vec[end]);
			return;
		}
	}
	else
	{
		if (vec[beg] > vec[end])
		{
			swap(vec[beg], vec[end]);
			return;
		}
		else
		{
			if (vec[mid] < vec[end]) swap(vec[mid], vec[end]);
			return;
		}
	}
}

int partition_Lomuto(std::vector<int> &vec, int beg, int end)//單向,加上一點優化
{
	int key = vec[end];
	while (vec[beg] < key)//可以避免已經排好的情況
	{
		if (++beg == end) return beg;
	}
	int next = beg + 1;
	for (; next < end; next++)
	{
		if (vec[next] < key)
		{
			swap(vec[next], vec[beg++]);
		}
	}
	swap(vec[beg], vec[end]);
	return beg;
}
int partition_Lomuto2(std::vector<int> &vec, int beg, int end)//單向,無優化
{
	int key = vec[end];
	for (int next = beg; next < end; next++)
	{
		if (vec[next] < key)
		{
			swap(vec[next], vec[beg++]);
		}
	}
	swap(vec[beg], vec[end]);
	return beg;
}
int partition_Hoare(std::vector<int> &vec, int beg, int end)//雙向
{
	int key = vec[end];
	while (beg<end)
	{
		while (beg < end && vec[beg] <= key) beg++;
		vec[end] = vec[beg];

		while (beg<end && vec[end] >= key)  end--;
		vec[beg] = vec[end];
	}
	vec[end] = key;
	return end;
}

void qsort_recusive(std::vector<int> &vec, int beg, int end)
{
	if (beg < end)
	{
		mid_of_three_swap(vec, beg, end);
		int index = partition_Hoare(vec, beg, end);
		qsort_recusive(vec, beg, index - 1);
		qsort_recusive(vec, index + 1, end);
	}
}
void qsort(std::vector<int> &vec)
{
	qsort_recusive(vec, 0, vec.size() - 1);
}

//mysort.h
#pragma once
#include<vector>
#include"algo.h"

void _mid_of_three_swap(std::vector<int>& vec, int beg, int end)
{
	int mid = beg + (end - beg) / 2;
	int mid_index;
	if (vec[beg] > vec[mid])
	{
		if (vec[mid] > vec[end])
		{
			swap(vec[mid], vec[end]);
			return;
		}
		else
		{
			if (vec[beg] < vec[end]) swap(vec[beg], vec[end]);
			return;
		}
	}
	else
	{
		if (vec[beg] > vec[end])
		{
			swap(vec[beg], vec[end]);
			return;
		}
		else
		{
			if (vec[mid] < vec[end]) swap(vec[mid], vec[end]);
			return;
		}
	}
}

int _lg(int n)
{
	int ret = 0;
	while (n>1)
	{
		ret++;
		n = n >> 1;
	}
	return ret;
}

int _partition_Hoare(std::vector<int> &vec, int beg, int end)
{
	int key = vec[end];
	while (beg<end)
	{
		while (beg < end && vec[beg] <= key) beg++;
		vec[end] = vec[beg];

		while (beg<end && vec[end] >= key)  end--;
		vec[beg] = vec[end];
	}
	vec[end] = key;
	return end;
}

void _insert(std::vector<int> &vec, int beg, int end)
{
	for (int i = beg+1; i <= end; i++)
	{
		int temp = vec[i];
		int j = i - 1;
		while (j >= beg && temp < vec[j])
		{
			vec[j + 1] = vec[j];
			j--;
		}
		vec[j + 1] = temp;
	}
}

void _down(std::vector<int> &vec, int i, int end)
{
	int child = i * 2 + 1;
	while (child < end)
	{
		if (child + 1 < end && vec[child] < vec[child + 1])
			child++;

		if (vec[i] < vec[child])
			swap(vec[i], vec[child]);
		else
			break;

		i = child;
		child = i * 2 + 1;
	}
}

void _heapsort(std::vector<int>& vec, int beg, int end)
{
	int m = end-beg+1;
	for (int i = beg + m / 2 - 1; i >= beg; i--)
	{
		_down(vec, i, m);
	}

	for (int i = beg + m - 1; i>beg; i--)
	{
		swap(vec[beg], vec[i]);
		_down(vec, beg, i);
	}

}

void _qsort_recusive(std::vector<int> &vec, int beg, int end, int depth_limit)
{
	if (--depth_limit == 0)
	{
		_heapsort(vec, beg, end);
		return;
	}
	if (end-beg>16)
	{
		_mid_of_three_swap(vec, beg, end);
		int index = _partition_Hoare(vec, beg, end);
		_qsort_recusive(vec, beg, index - 1, depth_limit);
		_qsort_recusive(vec, index + 1, end, depth_limit);
	}
	else
	{
		_insert(vec, beg, end);
	}
}

void mysort(std::vector<int> &vec)
{
	int m = vec.size();
	_qsort_recusive(vec, 0, m - 1, 2*_lg(m));
}

//main.h
#include<vector>
#include<iostream>
#include<ctime>
#include<algorithm>
#include"qsort.h"
#include"heapsort.h"
#include"sort.h"
#include"mergesort.h"
#include"mysort.h"
using namespace std;

void show(vector<int> &vec)
{
	for (auto x : vec)
	{
		cout << x << " ";
	}
	cout << endl;
}
void test()
{
	srand(time(0));
	vector<int> vec(10000000, 0);
	for (int i = 0; i < 10000000; i++)
	{
		vec[i] += rand() % 10000000;
	}
	vector<int> vec0(vec);
	vector<int> vec1(vec);
	vector<int> vec2(vec);
	vector<int> vec3(vec);
	vector<int> vec4(vec);
	vector<int> vec5(vec);
	vector<int> vec6(vec);
	cout << "數據量 " << vec.size() << endl;
	clock_t a, b;

	a = clock();
	sort(vec.begin(), vec.end());
	b = clock();
	cout << "stl " << b - a << endl;

	a = clock();
	mysort(vec0);
	b = clock();
	cout << "我的 " << b - a << endl;
	//show(vec0);

	a = clock();
	qsort(vec1);
	b = clock();
	cout << "快排 " << b - a << endl;

	a = clock();
	mergesort(vec2);
	b = clock();
	cout << "歸併 " << b - a << endl;

	a = clock();
	heapsort(vec3);
	b = clock();
	cout << "堆 " << b - a << endl;

	a = clock();
	xuanze(vec4);
	b = clock();
	cout << "選擇 " << b - a << endl;

	a = clock();
	maopao(vec5);
	b = clock();
	cout << "冒泡 " << b - a << endl;

	a = clock();
	insertsort(vec6);
	b = clock();
	cout << "插入 " << b - a << endl;
}
void main()
{
	test();
	char c; cin >> c;
}

單位:ms



內省快排,一方面限制了遞歸的深度適時採取堆排序,另一方面當範圍元素個數少時(16以下)採用插入排序。

只是在快排上做了一些微小的工作,性能上相較快排提升了不少,與stl裏的sort性能也接近了不少。

stl的sort分析見:http://www.udpwork.com/item/12284.html

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