常见排序算法
Posted virgildevil
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常见排序算法相关的知识,希望对你有一定的参考价值。
常见排序算法
编写代码并测试了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;
}
以上是关于常见排序算法的主要内容,如果未能解决你的问题,请参考以下文章