常见排序算法大全

各种排序算法


以下排序均实现从小到大的排序,且数据相同

冒泡排序

  • 重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。
void buttle_sort(int* ar, int len)
{
	int temp;
	for (int i = 0; i < len - 1; i++)
	{
		for (int j = 0; j < len - i - 1; j++)
		{
			if (ar[j] < ar[j - 1])
			{
				temp = ar[j];
				ar[j] = ar[j - 1];
				ar[j - 1] = temp;
			}
		}
	}
}

选择排序

  • 选择排序是一种简单直观的排序算法。依次从序列中找出最小(最大)的元素,放在开头,再次寻找最小(最大)的元素,放在已排序好 的序列的末尾,以此类推
void choice_sort(int* ar, int len)
{
	int temp;
	for (int i = 0; i < len - 1; i++)
	{
		int minIdx = i;
		for (int j = i + 1; j < len; j++)
		{
			minIdx = (ar[minIdx] < ar[j]) ? minIdx : j;
		}
		temp = ar[i];
		ar[i] = ar[minIdx];
		ar[minIdx] = temp;
	}
}

插入排序

  • 依次遍历元素,寻找一个合适的最小(最大)的元素,并逐个与不合适的元素交换位置,实现插入,最后将其放到一个排好序的有序列表中
void insert_sort(int* ar, int len)
{
	int temp;
	for (int i = 1; i < len; i++)
	{
		temp = ar[i];
		int j = i;
		while (j && ar[j - 1] > temp)
		{
			ar[j] = ar[j - 1];
			j--;
		}
		ar[j] = temp;
	}
}

希尔排序

  • 希尔排序是快速的插入排序,通过引入step(步长)来缩插入排序的待交换位置两个元素之间的距离,并且步长依次减少
//希尔排序
void Shell_sort(int* ar, int len)
{
	//拆分进行插入排序
	int step = len / 2;
	int temp;
	while (step)
	{
		for (int i = step; i < len; i += step)
		{
			temp = ar[i];
			int j = i;
			while (j && ar[j - step] > temp)
			{
				ar[j] = ar[j - step];
				j -= step;
			}
			ar[j] = temp;
		}

		step /= 2;
	}
}

计数排序

  • 计数排序是最简单的排序,把元素的值直接当作下标来使用,通过元素值来形成一个新的序列,基数排序不适用于重复元素与负值元素,需要重新实现细节
void jishu_sort(int* ar, int len, int max)
{
   	
	int k = 0;
	int lengh = max + 1;
	//1. 根据数组中最大的元素创建一个临时数组
	int* pTemp = new int[lengh];

	//2. 临时数组随便赋一个初始值
	for (int i = 0; i < max+1; i++)
	{
		pTemp[i] = -999;
	}
	//3. 根据下标排列
	for (int i = 0; i < len; i++)
	{
		pTemp[ar[i]] = ar[i];
	}
	//4. 重新整理数组

	for (int i = 0; i < max+1; i++)
	{
		if (pTemp[i] != -999)
		{
			ar[k++] = pTemp[i];
		}
	}
	//释放临时数组
	delete[] pTemp;

}

桶排序

  • 相当于改进版的计数排序,创建桶集合,每个桶存放着对应的数字位数,依次遍历数组序列的每一位,把合适的元素放入桶中,最后二维数组桶中按顺序存放着的就是数组排好序的结果
void bucket_sort(int* ar, int len)
{
	//1. 创建桶 每一位有10个数字  创建一个10行len列的桶集合
	int** pTemp = new int* [10];
	for (int i = 0; i < 10; i++)
	{
		//每一个桶都要有足够的空间装下整个数组的数字
		pTemp[i] = new int[len];
	}
	int bit_data;		//存储每一位的数字
	int num = 1;
	int index = 0;		
	while (num < BIGGEST)
	{
		//1. 首先给桶赋初始值
		for (int i = 0; i < 10; i++)
		{
			for (int j = 0; j < len; j++)
			{
				pTemp[i][j] = -999;
			}
		}

		//2. 数据按每位的数字大小依次进桶
		for (int i = 0; i < len; i++)
		{
			bit_data = ar[i] / num % 10;

			//进桶
			pTemp[bit_data][i] = ar[i];
		}

		//3. 桶里的数据覆盖原始数据
		index = 0;
		for (int i = 0; i < 10; i++)
		{
			for (int j = 0; j < len; j++)
			{
				if (-999 != pTemp[i][j])
				{
					ar[index++] = pTemp[i][j];
				}
			}
		}
		//travel(ar, len, false);
		num *= 10;		//位数依次变化  个 十 百 千
	}
	for (int i = 0; i < len; i++)
	{
		//释放列
		delete pTemp[i];
	}
	//释放行
	delete[] pTemp;
}

二分查找

  • 给定中间下标,通过分治的思想,找出指定的元素

//循环版 二分查找
bool isthisNUM(int* ar, int len,int num)
{
	/*
	从小到大
	*/
	int left = 0;
	int right = len - 1;
	int middle = 0;

	while (left <= right)
	{
		middle = left + (right - left) / 2;
		if (ar[middle] == num)
		{
			return true;
		}
		if (num > ar[middle])
		{
			/*
			数字大于中间值
			*/
			left = middle + 1;
		}
		else if (num < ar[middle])
		{
			right = middle - 1;
		}
	}
	return false;
}

//递归版 二分查找
bool isthisNUM_DIGUI(int* ar, int left,int right, int num)
{
	int middle = 0;

	while (left <= right)
	{
		middle = left + (right - left) / 2;
		if (num > ar[middle])
		{
			return isthisNUM_DIGUI(ar, middle + 1, 
                                   right, num);
		}
		else if (num < ar[middle])
		{
			return isthisNUM_DIGUI(ar, left, middle - 1,
                                   num);
		}
		else
		{
			return true;
		}
	}


	return false;
}

归并排序

  • 采用分治的思想,将数组利用递归分成若干个子数组,再排序已经分好的子数组,最后再将子数组合并为一个有序数组
//调用归并函数
void Invoking_Func(int* ar, int left, int right)
{
	Split_Arr(ar, left, right);
}
//两个数组的拆分排序
void Split_Arr(int* ar, int left, int right)
{
	int middle = 0;
	if (left < right)
	{
		middle = left + (right - left) / 2;
		//拆分归并
		Split_Arr(ar, left, middle);
		Split_Arr(ar, middle + 1, right);
		//合并算法
		Merge_Algorithm(ar, left, middle, right);
	}

}
//归并算法
void Merge_Algorithm(int* ar, int left, int middle, int right)
{
	int start_left = left;		//范围left - middle
	int start_right = middle+1;	//范围middle+1 - right
	int pTemp_index = 0;		//临时数组的下标
	//1. new创建一个临时存储数组
	int* pTemp = new int[right - left + 1];
	//2. 两个数组中的元素依次比较,放入临时数组中
	while (start_left <= middle && start_right <= right)
	{
		if (ar[start_left] < ar[start_right])
		{
			pTemp[pTemp_index++] = ar[start_left++];
		}
		else
		{
			pTemp[pTemp_index++] = ar[start_right++];
		}
	}
	//3. 将比较完成后多余的元素放入临时数组中
	while (start_left <= middle)
	{
		pTemp[pTemp_index++] = ar[start_left++];
	}
	while (start_right <= right)
	{
		pTemp[pTemp_index++] = ar[start_right++];
	}
	//4. 临时数组的内容拷贝到原数组
	memcpy(ar + left, pTemp, sizeof(int) * (right - left + 1));
	//5. 释放临时数组
	delete[]pTemp;
}

快速排序

  • 采用分治的思想,指定一个中间值,将数组分成两块,假设左半区要小于(大于)中间值,否则将此不符合的元素放在右半区,右半区要大于(小于)中间,否则将此不符合的元素放在左半区,下标指针依次移动,最终形成一个有序数组
//调用快速排序函数
void Quick_Func(int* ar, int left, int right)
{
	quickSort(ar, left, right);
}
//分组排序  快速排序算法
void quickSort(int* ar, int left, int right) {
	/*
	停止条件:  直到无法分为止
	*/
	if (left >= right)
	{
		return;
	}
	//1. 找一个指定的值作为中间值temp l指向left r指向right
	int start_left = left;		//不大于的区域   假设ar[start_left]是中间值
	int start_right = right;	//不小于的区域
	int temp = ar[start_left];	//临时中间值
	//2. 如果l和r不合并的情况下
	while (start_left < start_right)
	{
		while (start_left < start_right && ar[start_right] >= temp)
		{
			start_right--;
		}
		ar[start_left] = ar[start_right];
		while (start_left < start_right && ar[start_left] <= temp)
		{
			start_left++;
		}
		ar[start_right] = ar[start_left];
	}
	// 最后 l和r到达同一位置,中间值覆盖ar[l]或ar[r]
	ar[start_left] = temp;
	/*printf("left:%d,mid:%d,right:%d\n", left, start_left, right);
	Show(ar, NUM);*/
	//3. 重复分组合并
	quickSort(ar, left, start_left - 1);
	quickSort(ar, start_left + 1, right);
}


各种排序算法时间比较

在这里插入图片描述

/*
头文件
*/
#pragma once
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <Windows.h>
using namespace std;
#define NUM 100000
#define MAX_NUM 100000

//qsort排序
int comp1(const void* a, const void* b);

class Sort
{
private:
	int* ar;
	int len;
	time_t time1 = 0;
	time_t time2 = 0;
	
public:
	//默认构造函数
	Sort() { len = 0; ar = nullptr; }
	Sort(int l)
	{
		len = l;
		ar = new int[len];
	}
	Sort(const Sort& s);
	//析构函数
	~Sort() { delete[] ar; }
	//初始化数组
	void InitArr();
	//遍历数组
	void ShowArr(bool fg = false);
	//获得数组元素最大值
	int Get_max();
	//冒泡排序
	void bubble_sort();
	//选择排序
	void choice_sort();
	//插入排序
	void insert_sort();
	//希尔排序
	void shell_sort();
	//基数排序
	void radix_sort(int max);
	//桶排序
	void bucket_sort();
	//归并排序
	void merge_sort(int left, int right);
	void Merge_Sort(int left, int middle, int right);
	//快速排序
	void quick_sort(int left, int right);
	
	//接口修改时间
	time_t& GetTime1()
	{
		return time1;
	}
	time_t& GetTime2()
	{
		return time2;
	}
	//接口访问
	time_t GetTime1()const
	{
		return time1;
	}
	time_t GetTime2()const
	{
		return time2;
	}
	int* GetArr()
	{
		return ar;
	}

	//重载赋值运算符
	Sort& operator=(const Sort& s);
};
/*
实现文件
*/
#include "time.h"

Sort::Sort(const Sort& s)
{
	this->len = s.len;
	this->ar = new int[this->len];
	memcpy(this->ar, s.ar, sizeof(int) * this->len);
}

void Sort::InitArr()
{
	for (int i = 0; i < len; i++)
	{
		ar[i] = rand() % MAX_NUM;
	}
}

void Sort::ShowArr(bool fg)
{
	if (!fg)
	{
		cout << "排序前: \n";
	}
	else
	{
		cout << "排序后: \n";
	}
	for (int i = 0; i < len; i++)
	{
		cout << ar[i] << " ";
	}
	cout << "\n";
}

int Sort::Get_max()
{
	int max = ar[0];
	for (int i = 0; i < len; i++)
	{
		if (max < ar[i])
		{
			max = ar[i];
		}
	}

	return max;
}


void Sort::bubble_sort()
{
	int temp;
	for (int i = 0; i < len - 1; i++)
	{
		for (int j = 0; j < len - i - 1; j++)
		{
			if (ar[j] > ar[j + 1])
			{
				temp = ar[j];
				ar[j] = ar[j + 1];
				ar[j + 1] = temp;
			}
		}
	}
}


void Sort::choice_sort()
{
	int minIdx;
	int temp;
	for (int i = 0; i < len - 1; i++)
	{
		minIdx = i;
		for (int j = i + 1; j < len; j++)
		{
			minIdx = (ar[minIdx] < ar[j]) ? minIdx : j;
		}
		temp = ar[i];
		ar[i] = ar[minIdx];
		ar[minIdx] = temp;
	}
}

void Sort::insert_sort()
{
	int temp;
	int j;
	for (int i = 1; i < len; i++)
	{
		temp = ar[i];
		j = i;
		while (j && ar[j - 1] >= temp)
		{
			ar[j] = ar[j - 1];
			j--;
		}
		ar[j] = temp;
	}
}

void Sort::shell_sort()
{
	//希尔排序  分组进行插入排序
	int step = len / 2;
	int temp;
	int j;
	while (step)
	{
		for (int i = step; i < len; i += step)
		{
			temp = ar[i];
			j = i;
			while (j && ar[j - step] >= temp)
			{
				ar[j] = ar[j - step];
				j -= step;
			}
			ar[j] = temp;
		}

		step /= 2;
	}
}

void Sort::radix_sort(int max)
{
	int p_index = 0;
	//1.  创建一个足够大的临时数组
	int* pTemp = new int[max + 1];

	//2. 临时数组赋值初始
	for (int i = 0; i < max + 1; i++)
	{
		pTemp[i] = -999;
	}

	//3. 对应下标赋值
	for (int i = 0; i < len; i++)
	{
		pTemp[ar[i]] = ar[i];
	}

	//4. 覆盖回原数组
	for (int i = 0; i < max + 1; i++)
	{
		if (pTemp[i] != -999)
		{
			ar[p_index++] = pTemp[i];
		}
	}
	delete[] pTemp;
}

void Sort::bucket_sort()
{
	int num = 1;			//从个位开始
	int bit_data;			//存储各位数字
	//1. 创建临时桶集合
	int** p = new int* [10];
	for (int i = 0; i < 10; i++)
	{
		p[i] = new int[len];
	}

#if 1
	while (num<MAX_NUM)
	{
		//2. 桶初始化
		for (int i = 0; i < 10; i++)
		{
			for (int j = 0; j < len; j++)
			{
				p[i][j] = -999;
			}
		}

		//3.各位数字比较  然后入桶
		for (int i = 0; i < len; i++)
		{
			bit_data = ar[i] / num % 10;

			p[bit_data][i] = ar[i];
		}

		//4. 覆盖回原数组
		int t_index = 0;		//新数组下标
		for (int i = 0; i < 10; i++)
		{
			for (int j = 0; j < len; j++)
			{
				if (p[i][j] != -999)
				{
					ar[t_index++] = p[i][j];
				}
			}
		}

		num *= 10;
	}
#else
#endif
	for (int i = 0; i < 10; i++)
	{
		delete[] p[i];
	}
	delete[] p;
}

void Sort::merge_sort(int left, int right)
{
	int middle = 0;
	if (left < right)
	{
		middle = left + (right - left) / 2;
		merge_sort(left, middle);
		merge_sort(middle + 1, right);
		Merge_Sort(left, middle, right);
	}
}

void Sort::Merge_Sort(int left, int middle, int right)
{
	int sL = left;			//left - middle 范围
	int sR = middle + 1;	//middle+1 - right	范围
	int t_index = 0;		//临时数组下标
	//1. 创建临时数组
	int* pTemp = new int[right - left + 1];
	//2. 两个数组中的元素依次比较 放入临时数组
	while (sL <= middle && sR <= right)
	{
		if (ar[sL] < ar[sR])
		{
			pTemp[t_index++] = ar[sL++];
		}
		else
		{
			pTemp[t_index++] = ar[sR++];
		}
	}
	//3. 多余的元素接着放入
	while (sL <= middle)
	{
		pTemp[t_index++] = ar[sL++];
	}
	while (sR <= right)
	{
		pTemp[t_index++] = ar[sR++];
	}
	//4.覆盖回原数组
	memcpy(ar + left, pTemp, sizeof(int) * (right - left + 1));
	//5.释放临时数组
	delete[] pTemp;
}

void Sort::quick_sort(int left, int right)
{
	if (left >= right)
	{
		return;
	}
	//找中间值  sL和sR与中间值进行比较
	int sL = left;		//指向数组起点
	int sR = right;		//指向数组末尾	
	int temp = ar[sL];	//中间值

	//分组进行快排
	while (sL < sR)
	{
		while (sL < sR && ar[sR] >= temp)
		{
			sR--;
		}
		ar[sL] = ar[sR];
		while (sL < sR && ar[sL] <= temp)
		{
			sL++;
		}
		ar[sR] = ar[sL];
	}
	ar[sL] = temp;

	//继续拆分
	quick_sort(left, sL - 1);
	quick_sort(sL + 1, right);
}

Sort& Sort::operator=(const Sort& s)
{
	this->len = s.len;
	this->ar = new int[this->len];
	memcpy(this->ar, s.ar, sizeof(int) * this->len);
	return *this;
}



int comp1(const void* a, const void* b)
{
	if (*(int*)a > *(int*)b)
	{
		return 1;
	}
	else if (*(int*)a < *(int*)b)
	{
		return -1;
	}
	else
	{
		return 0;
	}
}

#include "time.h"

time_t time1 = 0;
time_t time2 = 0;

int main()
{
	srand(time(0));

	Sort ar1(NUM);
	ar1.InitArr();
	Sort ar2;
	ar2 = ar1;
	Sort ar3(ar1);
	Sort ar4(ar1);
	Sort ar5;
	ar5 = ar1;
	Sort ar6(ar1);
	Sort ar7(ar1);
	int* arr_sort = new int[NUM];
	memcpy(arr_sort, ar1.GetArr(), sizeof(int) * NUM);

	cout << "10w 个数据的排序算法比较: \n\n";
#if 1
#if 1
	ar1.GetTime1() = GetTickCount();
	ar1.bubble_sort();
	ar1.GetTime2() = GetTickCount();
	cout << "冒泡排序用时: " << ar1.GetTime2() - ar1.GetTime1()
		<< "ms" << endl;

	
	ar2.GetTime1() = GetTickCount();
	ar2.choice_sort();
	ar2.GetTime2() = GetTickCount();
	cout << "选择排序用时: " << ar2.GetTime2() - ar2.GetTime1()
		<< "ms" << endl;

	ar3.GetTime1() = GetTickCount();
	ar3.insert_sort();
	ar3.GetTime2() = GetTickCount();
	cout << "插入排序用时: " << ar3.GetTime2() - ar3.GetTime1()
		<< "ms" << endl;
#endif
	ar4.GetTime1() = GetTickCount();
	ar4.shell_sort();
	ar4.GetTime2() = GetTickCount();
	cout << "希尔排序用时: " << ar4.GetTime2() - ar4.GetTime1()
		<< "ms" << endl;

	ar5.GetTime1() = GetTickCount();
	ar5.bucket_sort();
	ar5.GetTime2() = GetTickCount();
	cout << "桶排序用时: " << ar5.GetTime2() - ar5.GetTime1()
		<< "ms" << endl;

	ar6.GetTime1() = GetTickCount();
	ar6.merge_sort(0,NUM-1);
	ar6.GetTime2() = GetTickCount();
	cout << "归并排序用时: " << ar6.GetTime2() - ar6.GetTime1()
		<< "ms" << endl;

	ar7.GetTime1() = GetTickCount();
	ar7.quick_sort(0, NUM - 1);
	ar7.GetTime2() = GetTickCount();
	cout << "快速排序用时: " << ar7.GetTime2() - ar7.GetTime1()
		<< "ms" << endl;

	time1 = GetTickCount();
	qsort(arr_sort, NUM, sizeof(int), comp1);
	time2 = GetTickCount();
	cout << "qsort排序用时: " << time2 - time1
		<< "ms" << endl;
	cout << "基数排序暂不在讨论范围内" << endl;
#endif
	return 0;
}
``

posted @ 2022-07-30 09:10  hugeYlh  阅读(12)  评论(0编辑  收藏  举报  来源