7种常见排序算法的c++实现

今天心血来潮复习了一下基本的排序算法,实现了一下,就顺便发上来咯。。

在代码里做了注释了-。-

也就不多说了,直接上代码吧。。

// order_algorithm.cpp: 定义控制台应用程序的入口点。
//author: netbin

#include "stdafx.h"
#include "iostream"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <vector>

//指定数组的大小
const int max_size = 50;

using namespace::std;

//插入排序
//时间复杂度O(n^2),空间复杂度O(n),是一个稳定算法;
//假定该数组有有序区和无序区:则不断地将无序区的第一个元素取出放置于有序区的正确位置;
//从i的位置开始,从后往前依次比较,如果nums[j]小于nums[i],则交换二者的位置;
//优化:我们可以知道插入排序的前部是有序的,则如果nums[j]>=nums[i],则表明,i之前的所有元素
//都符合这个特性,那么也就不需要再继续比较了;
void insert_sort(vector<int> &nums) 
{
	for (int i = 0; i < nums.size(); i++) {
		for (int j = i; j > 0; j--) {
			if (nums[j] < nums[j-1]) {
				int temp = nums[j];
				nums[j] = nums[j-1];
				nums[j-1] = temp;
			}
			else
				break;
		}
	}
}

//希尔排序
//时间复杂度 O(n^1.3),准确地说希尔排序的时间复杂度与增量序列有关
//它是一个不稳定的算法:因为可能数处于不同的组别内
//希尔排序是对插入排序的优化
void shell_sort(vector<int> &nums) 
{
	//gap是步长,步长每次减半;
	//这里最后的gap/=2要注意。。刚开始写成了gap/2,没有等号,所有gap没作用,会造成死循环
	for (int gap = nums.size() / 2; gap > 0; gap /= 2) {
		//从gap位置开始,相当于直接插入排序的第2个元素开始;
		for (int i = gap; i < nums.size(); i++) {
			int temp = nums[i];
			//相当于插入排序的j = i;
			//同组内的无序数组的第一个元素的前一个数组。。。好像挺绕的-。-
			int j = i - gap;
			//同组内元素的比较
			for (; j >= 0 && nums[j] > temp; j -= gap) {
				//这里需要注意的是j的值变化的情况;
				//第一次的j+gap=i #-。-
				//其实也就是把大于nums[i]的值都后移
				nums[j + gap] = nums[j];
			}
			//这里需要注意的是在上面的for循环中,最后还会执行一次j-=gap;
			//所以这里的j+gap会等于上面结束时j的值
			nums[j + gap] = temp;
		}
	}
}

//冒泡排序
//时间复杂度: O(n^2),空间复杂度:O(n)
//稳定性:是一个稳定算法
void bubble_sort(vector<int> &nums) 
{
	for (int i = 0; i < nums.size()-1; i++) {
		for (int j = 0; j < nums.size() - i - 1; j++) {
			if (nums[j] > nums[j + 1]) {
				int temp = nums[j];
				nums[j] = nums[j + 1];
				nums[j + 1] = temp;
			}
		}
	}
}

//选择排序:从无序数组中选出最小(最大)的数,放到乱序数组的头部
//优化:同时选出最大和最小
void select_sort(vector<int> &nums)
{
	for (int i = 0; i < nums.size(); i++) {
		int min = i;
		for (int j = i+1; j < nums.size(); j++) {
			if (nums[j] < nums[min]) {
				min = j;
			}
		}
		int temp = nums[i];
		nums[i] = nums[min];
		nums[min] = temp;
	}
}

//快速排序
void quick_sort(vector<int> &nums, int b, int e, vector<int> &temp)
{
	int m = (b + e) / 2;
	//判断是否只有一个元素
	if (m != b) {
		int lb = b;
		int rb = e - 1;
		for (int i = b; i < e; i++) {
			//如果当前位置等于选中元素的位置,则跳过此次循环,进入下一次循环;
			if (i == m) {
				continue;
			}
			//如果当前位置元素的值小于选中的元素,则添加到临时数组的左边
			if (nums[i] < nums[m]) {
				temp[lb++] = nums[i];
			}else{
				//如果当前位置元素的值大于选中的元素,则添加到临时数组的右边
				temp[rb--] = nums[i];
			}
		}
		//循环结束时,temp数组中lb指向的位置就是在nums数组中选中元素所在的位置
		temp[lb] = nums[m];
		//将temp数组复制到nums数组中
		for (int i = b; i < e; i++) {
			nums[i] = temp[i];
		}
		//递归调用
		quick_sort(nums,b,lb,temp);
		quick_sort(nums, lb + 1, e, temp);
	}
}


//归并排序
//时间复杂度:O(nlogn)
//归并排序是将元素分割为一个一个的小组,然后对每个小组再进行排序,然后再合并数组,分而治之的思想
//这种排序的方式与希尔排序的基本思想类似
void merge_array(vector<int> &nums, int b, int m, int e, vector<int> &temp)
{
	int lb = b;
	int rb = m;
	int tb = b;
	//在合并两个数组时,如果左边数组和右边的数组都未空
	while (lb != m && rb != e) {
		if (nums[lb] < nums[rb]) {
			temp[tb++] = nums[lb++];
		}
		else {
			temp[tb++] = nums[rb++];
		}
	}
	//如果右边的已经空了,而左边没空,就将左边数组的剩余所有元素全部入数组
	while (lb < m)
		temp[tb++] = nums[lb++];
	//如果左边的已经空了,而右边没空,就将右边数组的剩余所有元素全部入数组
	while (rb < m)
		temp[tb++] = nums[rb++];
	//将此次合并存入临时数组的元素全部复制到nums数组中
	for (int i = b; i < e; i++) {
		nums[i] = temp[i];
	}
}

void merge_sort(vector<int> &nums, int b, int e, vector<int> &temp)
{
	int m = (b + e) / 2;
	if (m != b) {
		//将元素分割成一个一个的
		merge_sort(nums, b, m, temp);
		merge_sort(nums, m, e, temp);
		//然后对这些元素组成的小组进行递归合并;
		merge_array(nums, b, m, e, temp);
	}
}

//堆排序
//建堆以及调整堆
void max_heapofy(vector<int> &nums, int beg, int end)
{
	int curr = beg;
	int child = curr * 2 + 1;
	//不是最后一个结点
	while (child < end) {
		//判断子结点中哪个更大,用最大子节点来和父节点比较就可以了
		if (child + 1 < end && nums[child + 1] > nums[child])
			child++;
		//如果父节点小于最大子节点,就交换值
		if (nums[curr] < nums[child]) {
			int temp = nums[curr];
			nums[curr] = nums[child];
			nums[child] = temp;
			//调整之后可能会导致下面的子树不是最大堆,故而要重新调整
			curr = child;
			child = curr * 2 + 1;
		}
		else
			//如果不需要调整,则结束此次循环
			break;
	}
}

void heap_sort(vector<int> &nums)
{
	int n = nums.size();
	//建堆
	for (int i = n / 2 - 1; i >= 0; i--) {
		max_heapofy(nums,i,nums.size());
	}
	//将堆顶(最大元素)和数组的最后一个值交换,然后再调整堆
	for (int i = n - 1; i > 0; i--) {
		int temp = nums[i];
		nums[i] = nums[0];
		nums[0] = temp;
		max_heapofy(nums,0,i);
	}
}

//初始化vector数组函数
void init_vec(vector<int> &nums)
{
	srand((unsigned)time(NULL));
	for (int i = 0; i < max_size; i++) {
		nums.push_back(rand());
	}
}
//输出结果,并清空vector
void print_clear(vector<int> &nums)
{
	for (int i = 0; i < max_size; i++) {
		cout << nums[i] << "  ";
	}
	cout << endl;
	nums.clear();
}


int main()
{
	vector<int> nums;

	//插入排序:测试结果成功
	init_vec(nums);
	time_t start = clock();
	insert_sort(nums);
	time_t end = clock();
	cout << "插入排序测试结果:" << endl;
	print_clear(nums);
	printf("运行时间 : %f\n", double(end - start) / CLOCKS_PER_SEC);


	//希尔排序:测试结果成功
	init_vec(nums);
	start = clock();
	shell_sort(nums);
	end = clock();
	cout << "希尔排序测试结果:" << endl;
	print_clear(nums);
	printf("运行时间 : %f\n", double(end - start) / CLOCKS_PER_SEC);

	//冒泡排序:成功
	init_vec(nums);
	start = clock();
	bubble_sort(nums);
	end = clock();
	cout << "冒泡排序测试结果:" << endl;
	print_clear(nums);
	printf("运行时间 : %f\n", double(end - start) / CLOCKS_PER_SEC);

	//选择排序:成功
	init_vec(nums);
	start = clock();
	select_sort(nums);
	end = clock();
	cout << "选择排序测试结果:" << endl;
	print_clear(nums);
	printf("运行时间 : %f\n", double(end - start) / CLOCKS_PER_SEC);

	//快速排序:成功
	vector<int> temp(max_size);
	init_vec(nums);
	start = clock();
	quick_sort(nums,0,nums.size(),temp);
	end = clock();
	temp.clear();
	cout << "快速排序测试结果:" << endl;
	print_clear(nums);
	printf("运行时间 : %f\n", double(end - start) / CLOCKS_PER_SEC);

	//归并排序:失败-。- 数组下表越界 #因为在快速排序时清空了temp数组,所以导致了这次的数组越界
	init_vec(temp);
	init_vec(nums);
	start = clock();
	merge_sort(nums, 0, nums.size(), temp);
	end = clock();
	temp.clear();
	cout << "归并排序测试结果:" << endl;
	print_clear(nums);
	printf("运行时间 : %f\n", double(end - start) / CLOCKS_PER_SEC);
	

	//堆排序:失败-。-最后一个元素没有排好序
	//修复了 #-。-
	init_vec(nums);
	start = clock();
	heap_sort(nums);
	end = clock();
	temp.clear();
	cout << "堆排序测试结果:" << endl;
	print_clear(nums);
	printf("运行时间 : %f\n", double(end - start) / CLOCKS_PER_SEC);

	system("pause");
    return 0;
}


猜你喜欢

转载自blog.csdn.net/weixin_41713281/article/details/79427136