常见排序算法汇总(C++实现)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wk_bjut_edu_cn/article/details/83868468

插入排序

#include<iostream>
using namespace std;
/*
插入排序的细节讲解与复杂度分析
时间复杂度O(N ^ 2),额外空间复杂度O(1)
*/
void InsertSort(int *arr, int length)
{
	int i, j;
	int temp;
	if (arr == nullptr || length < 2)
		return;
	for (i = 1; i < length; ++i)
	{
		temp = arr[i];
		j = i - 1;
		while (j >= 0 && temp < arr[j])
		{
			arr[j + 1] = arr[j];
			--j;
		}
		//找到插入位置,将temp中待排元素插入
		arr[j + 1] = temp;
	}
}

int main(void)
{
	int arr[4] = { 4,3,2,1 };
	InsertSort(arr, 4);
	cout << arr[0] << arr[1] << arr[2] << arr[3] << endl;
	system("pause");
	return 0;
}

冒泡排序

#include<iostream>
using namespace std;
//将大的筛选筛选到后边
void BubbleSort(int *arr, int length)
{
	if (arr == nullptr || length < 2)
		return;
	int flag;//标记
	int temp;
	for (int i = length - 1; i >= 1; --i)
	{
		flag = 0;//变量flag用来标记本趟排序是否发生了交换
		for (int j = 1; j <= i; ++j)
		{
			if (arr[j - 1]>arr[j])
			{
				temp = arr[j];
				arr[j] = arr[j - 1];
				arr[j - 1] = temp;
				//如果未发生交换,则flag的值为0;如果发生交换,则flag的值为1
				flag = 1;
			}
		}
		//一趟排序过程中没有发生元素交换,则证明序列有序,排序结束
		if (flag == 0)
			return;
	}
}
int main(void)
{
	int arr[2] = { 5,0 };
	BubbleSort(arr, 2);
	for (auto i : arr)
		cout << i << " ";
	cout << endl;
	system("pause");
	return 0;
}

快速排序(改进版)

#include<iostream>
#include<ctime>
using namespace std;
#define random(x)(rand()%x)

//快速排序
/*
在经典快排的基础上,做了两个改动
1.不是选择数组的最后一个数,而是随机选择一个
2.经典的是以一个数为中间,然后左边小于等于,右边大于
而现在是左边小于的数组,中间全部是等于这个数的数组,
右边是大于的数组
*/
void swap(int *arr, int i, int j);
int *partition(int *arr, int l, int r);
void QuickSort(int *arr, int l, int r)
{
	if (l < r)
	{
		srand((int)time(0));
		/*
		经典快排是选择数组的最后一个数,现在改进的
		随机快排多了随机选择数组中的一个数作为比较对象,
		不一定非得是最后一个数
		*/
		swap(arr, random(r - l + 1)+l, r);
		int *p = partition(arr, l, r);
		QuickSort(arr, l, p[0] - 1);
		QuickSort(arr, p[1] + 1, r);
	}
}
int *partition(int *arr, int l, int r)
{
	int less = l - 1;
	int more = r;
	while (l < more)
	{
		if (arr[l] < arr[r])
		{
			swap(arr, ++less, l++);
		}
		else if (arr[l]>arr[r])
		{	
			swap(arr, --more, l);
		}
		else
		{
			l++;
		}
	}
	//more是>=r的第一个位置,所以最后将r放到它该在的位置
	swap(arr, more, r);//将最后一位作为比较的数移到它该在的位置
	int *p = new int[2]{ less + 1,more };//遗留问题---------什么时候进行delete
	return p;
}

void swap(int *arr, int i, int j)
{
	int temp = arr[i];
	arr[i] = arr[j];
	arr[j] = temp;
}

int main(void)
{
	int i_arr[] = { 2,6,4,8,1,2,8,3};
	QuickSort(i_arr, 0, 7);
	for (int i : i_arr)
		cout << i << "	";
	cout << endl;
	system("pause");
	return 0;
}

简单选择排序

#include<iostream>
using namespace std;
void SelectSort(int *arr, int length)
{
	int index, temp;
	for (int i = 0; i < length - 1; ++i)
	{
		index = i;//当前的最小元素
		//从无序数组中挑出一个最小的元素
		for (int j = i + 1; j <= length - 1; ++j)
			if (arr[j] < arr[index])
				index = j;
		//完成最小元素与无序序列中第一个元素的交换
		temp = arr[i];
		arr[i] = arr[index];
		arr[index] = temp;
	}
}
int main(void)
{
	int arr[6] = { 6,5,4,3,2,1 };
	SelectSort(arr, 6);
	for (auto i : arr)
		cout << i << " ";
	cout << endl;
	system("pause");
	return 0;
}

堆排序

#include<iostream>
using namespace std;
/*
本函数完成对在arr[low]到arr[high]范围内对在位置
low上的节点进行调整
*/
void Sift(int *arr, int low, int high)
{
	int i = low, j = 2 * i;
	int temp = arr[i];
	while (j <= high)
	{
		//右孩子存在且比左孩子大
		if (j < high && arr[j] < arr[j + 1])
			++j;
		if (temp < arr[j])
		{
			arr[i] = arr[j];
			i = j;
			j = 2 * i;
		}
		else
			break;
	}
	//被调整的节点的值找到了它该在的位置
	arr[i] = temp;
}
//堆排序函数
void HeapSort(int *arr, int length)
{
	int i;
	int temp;
	//建立初始堆
	/*
	因为要通过2*i求左右节点,所以数组的第一个元素不参与
	*/
	for (i = (length-1) / 2; i >= 1; --i)
		Sift(arr, i, length - 1);
	//每次都将最大元素放到数组的后面
	for (i = length - 1; i >= 2; --i)
	{
		temp = arr[1];
		arr[1] = arr[i];
		arr[i] = temp;
		//在减少了1个元素的无序序列中进行调整
		Sift(arr, 1, i - 1);
	}
}

int main(void)
{
	int arr[6] = {-1,35,43,26,95,48};
	HeapSort(arr, 6);
	for (auto i : arr)
		cout << i << " ";
	cout << endl;
	system("pause");
	return 0;
}

二路归并排序

#include<iostream>
using namespace std;
/*
该函数实现的是合并两个有序子序列
*/
void Merge(int *arr, int low, int high, int mid)
{
	int num1 = mid - low + 1;
	int num2 = high - mid;
	//将左半部分的有序子序列存到数组left中
	int *left = new int[num1];
	//将右半部分的有序子序列存到数组right中
	int *right = new int[num2];
	int i, j, k;
	for (i = 0; i < num1; ++i)
		left[i] = arr[low + i];
	for (j = 0; j < num2; ++j)
		right[j] = arr[mid + 1 + j];

	//比较两个有序数组中的元素,每次都在找较小的元素
	i = 0, j = 0, k = low;
	while (i < num1 && j < num2)
	{
		if (left[i] < right[j])
			arr[k++] = left[i++];
		else
			arr[k++] = right[j++];
	}
	//如果某个数组中还有元素,则把剩余部分全部拷入arr中,
	//注意,不可能两个数组都还有元素
	while (i < num1)
		arr[k++] = left[i++];
	while (j < num2)
		arr[k++] = right[j++];

	delete[]left;
	delete[]right;
}
/*
二路归并排序
递归的方式进行,总是对两组有序数组进行排序
*/
void MergeSort(int *arr, int low, int high)
{
	if (low < high)
	{
		int mid = (low + high) >> 1;
		MergeSort(arr, low, mid);
		MergeSort(arr, mid + 1, high);
		Merge(arr, low, high, mid);
	}
}
int main(void)
{
	int arr[6] = {2,4,3,2,6,1};
	MergeSort(arr, 0, 5);
	for (auto i : arr)
		cout << i << " ";
	cout << endl;
	system("pause");
	return 0;
}

希尔排序

#include<iostream>
#include<vector>
using namespace std;
void print(const vector<int>& data);
void ShellInsert(vector<int>&data, int num)
{
	for (int i = num; i < data.size(); ++i)
	{
		//说明需要进行调整,其实这部分就相当于是插入排序
		if (data[i] < data[i - num])
		{
			int temp = data[i];
			int j;

			for (j = i - num; j >= 0 && temp < data[j]; j -= num)
				data[j + num] = data[j];
			data[j + num] = temp;
		}
	}
	cout << "delta" << num << ":";
	print(data);
	cout << endl;
}
/*
data是待排序的数组
dalta是增量数组,可以由自己设定,一般5、3、1
*/
void ShellSort(vector<int>&data, vector<int>&delta)
{
	for (int i = 0; i < delta.size(); ++i)
		ShellInsert(data, delta[i]);
}
void print(const vector<int>& data)
{
	for (auto i : data)
		cout << i << " ";
}
int main(void)
{
	vector<int> data{ 2,4,8,5,3,9,6 };
	vector<int> delta{ 5,3,1 };
	ShellSort(data, delta);
	system("pause");
	return 0;
}

基数排序

#include<iostream>
using namespace std;
/*
求一个数组中的元素的最大位数,以决定排序次数
*/
int MaxBit(int *data, int length)
{
	int d = 1;//保存最大的位数
	int p = 10;
	for (int i = 0; i < length; ++i)
	{
		while (data[i] > p)
		{
			p *= 10;
			++d;
		}
	}
	//返回最大位数,比如数组中最大的元素是345,则返回的位数为3
	return d;
}
//基数排序
void RadixSort(int *data, int length)
{
	int d = MaxBit(data, length);
	//从桶0-9,存放这些桶中的元素,相当于是已经排序依次以后的顺序
	int *bucket = new int[length]; 
	//桶中元素的计数器,count[0]表示第0个桶中存放的元素个数,依次类推
	int *count = new int[10];
	int i, j, k;
	int radix = 1;
	//最大位数是几,就要进行几次怕排序
	for (i = 1; i <= d; ++i)
	{
		for (j = 0; j < 10; ++j)
			count[j] = 0;//每次分配前都要清空计数器
		for (j = 0; j < length; ++j)
		{
			k = (data[j] / radix) % 10;//统计每个桶中元素的个数,第一轮统计个位,第二轮十位,以此类推
			count[k]++;//保存到计数器中
		}
		/*
		这个是难点,在这卡了10分钟,count[i]表示第i个桶的右边界索引
		*/
		for (j = 1; j < 10; ++j)
			count[j] += count[j - 1];
		//从后向前放,比如个位数相同,后出现的在后面放,保持了稳定性
		//bucket数组中的数就是这一轮排序之后的依次呈现
		for (j = length - 1; j >= 0; --j)
		{
			k = (data[j] / radix) % 10;
			bucket[count[k] - 1] = data[j];
			count[k]--;
		}
		//基数排序的收集,把桶中的数据再倒出来,然后进行前一位数的排序
		for (j = 0; j < length ; ++j)
			data[j] = bucket[j];

		for (int y = 0; y < length; ++y)
			cout << data[y] << " ";
		cout << endl;
		radix *= 10;
	}
	delete[]bucket;
	delete[]count;
}
int main(void)
{
	int arr[5] = { 2,567,238,904,123};
	RadixSort(arr, 5);
	for (auto i : arr)
		cout << i << " ";
	cout << endl;
	system("pause");
	return 0;
}

排序算法分析

n为元素的个数,d为关键字的位数,rd为桶数。

猜你喜欢

转载自blog.csdn.net/wk_bjut_edu_cn/article/details/83868468
今日推荐