使用C++实现十大基本算法排序

本文详细介绍了多种基础排序算法,包括冒泡排序、选择排序、插入排序、希尔排序、并归排序、快速排序、堆排序、计数排序、桶排序和基数排序,以及部分算法的实现过程。作者强调算法的简单实现,但提醒读者这些代码未经深入理论分析和优化。
摘要由CSDN通过智能技术生成

目录

前言

一、算法比较

二、算法实现(默认升序)

1、冒泡排序

2、选择排序

3、插入排序

4、希尔排序

5、并归排序

6、快速排序

7、堆排序

8、计数排序

9、桶排序

10、基数排序

总结


前言

        听说面试会容易问起这个简单的算法,所以复习一下顺便写个文章记录一下。

推荐一个可视化网站,可以看一些算法的运行步骤。

一、算法比较

二、算法实现(默认升序)

1、冒泡排序

   循环n-1次,每次从0开始与n比较,保证n为大值,直到循环到len-n时,此时的

//冒泡排序
void bubble_sort(int *nums,int len)
{
	for (int i = 0; i < len; i++)
	{
		//遍历整个数组寻找最大值,因为已经遍历了i次,寻找出了i个大值,所有只需要再遍历len-1-i次
		for (int j = 0; j < len-1-i; j++)
		{
			//判断两数大小,不符合排序规则就进行交换
			if (nums[j] > nums[j + 1])
			{
				int temp = nums[j];
				nums[j] = nums[j + 1];
				nums[j + 1] = temp;
			}
		}
	}
}

2、选择排序

遍历n-1次数组,每次寻找出最小值,存放在第n-1的位置上。

//选择排序
void select_sort(int *nums, int len)
{
	for (int i = 0; i < len-1; i++)
	{
		//记录最小值的下标
		int minIndex = i;

		for (int j = i+1; j < len; j++)
		{
			//判断新元素是否是小值
			if (nums[minIndex] > nums[j])
			{
				minIndex = j;
			}
		}
		//如果最小值不是i就进行交换
		if (i != minIndex)
		{
			int temp = nums[i];
			nums[i] = nums[minIndex];
			nums[minIndex] = temp;
		}
	}
}

3、插入排序

        循环n-1次,将n前面的数看作为有序排列,将n+1元素插入到前n个排列中。

//插入排序
void insert_sort(int *nums, int len)
{
	for (int i = 0; i < len-1; i++)
	{
		//将第i+1个元素插入前i个数中
		int cur = nums[i + 1];
		for (int j = i ; j >= 0; j--)
		{
			//查找插入的位置
			if (nums[j] > cur)
			{
				//i+1的值更小,往移位给i+1腾位置
				nums[j + 1] = nums[j];
			}
			else
			{
				//插入合适的位置
				nums[j + 1] = cur;
				break;
			}

		}
	}
}

4、希尔排序

        按照n/2的间距先进行元素的两两排序,然后将间距-1,直到间距为1。

//希尔排序
void shell_sort(int *nums, int len)
{
	//间距从len/2开始
	int temp, gap = len / 2;
	//间距>=1
	while (gap > 0)
	{
		for (int i = gap; i < len; i++)
		{
			//记录当前值
			temp = nums[i];
			//间距相同的上一个元素
			int preIndex = i - gap;
			while (nums[preIndex] > temp && preIndex >= 0)
			{
				//判断间距相同的前面的元素的大小
				nums[preIndex+gap] = nums[preIndex];
				preIndex -= gap;
			}
			nums[preIndex + gap] = temp;
		}
		gap /= 2;
	}
}

5、并归排序

        先将数组二分直到分成每个组只有1,然后再两两比较连接在一起。遍历了n/2次。

//并归排序
void merge(int *nums, int len)
{
	int *temp = new int[len];
	int index = 0;
	int mid = len / 2;
	int first = 0, second = mid;
	//二个有序数组合成一个
	while (first < mid && second < len)
	{
		//判断大小
		if (nums[first] < nums[second]) temp[index++] = nums[first++];
		else 	temp[index++] = nums[second++];
	}
	//将两边剩下的值进行写入
	while (first < mid) temp[index++] = nums[first++];
	while(second<len) temp[index++] = nums[second++];
	//赋值给返回值
	for (int i = 0; i < len; i++)
	{
		nums[i] = temp[i];
	}
}
void merge_sort(int *nums, int len)
{
	//当分成1之后就不能再分,返回递归
	if (len <= 1) return;
	if (len > 1)
	{
		//继续二分
		merge_sort(nums,len/2);
		merge_sort(nums+ len /2, len - len / 2);
		//进行融合
		merge(nums,len);
	}
}

6、快速排序

        利用了递归的思想,以初始值左值为基准将小于左值的数交换到左边,然后更换基准值位置进行递归排序。

//快速排序
void quick_sort(int nums[], int _left,int _right)
{
	int left = _left;
	int right = _right;
	//设置递归完成条件
	if (left >= right) return;
	//设置基准值
	int temp = nums[left];
	while (left != right)
	{
		//查找右边小于基准值,并进行交换
		while (temp <= nums[right] && right>left)  right--;
		nums[left] = nums[right];
		//查找左边大于基准值,并进行交换
		while (temp >= nums[left] && right > left) left++;
		nums[right] = nums[left];
		
	}
	//改变基准值
	nums[left] = temp;
	quick_sort(nums, _left, left-1);
	quick_sort(nums, right + 1, _right);
}

7、堆排序

        利用了二叉树的构造思想,将最大的元素放在堆顶部,然后与末尾位置进行交换。遍历n-1次

//堆排序
void heap_adjust(int *nums, int start, int end)
{
	int parent = start;
	int child = start * 2 + 1;
	while (child < end)
	{
		if (child + 1 < end && nums[child] < nums[child + 1])
		{
			//寻找两个节点的最大值
			child++;
		}
		if (nums[parent] > nums[child])
		{
			//不进行交换
			return;
		}
		else
		{
			//寻找到更大值,进行交换
			int temp = nums[parent];
			nums[parent] = nums[child];
			nums[child] = temp;
			//比较下一层节点
			parent = child;
			child = parent * 2 + 1;
		}
	}
}
void heap_sort(int *nums, int len)
{
	for (int i = len / 2 - 1; i >= 0; i--)
	{
		heap_adjust(nums,i,len);
	}

	for (int i = len - 1; i > 0; i--)
	{
		int temp = nums[0];
		nums[0] = nums[i];
		nums[i] = temp;		//交换顶点
		heap_adjust(nums,0,i);
	}
}

8、计数排序

        找出数组元素的最大值,申请最大值大小的数组并且初始化为0,然后将原数组的每个值作为新数组的下标进行++,最后遍历新数组判断其值是否>0,即可知道原数组值的排序。

//计数排序
void count_sort(int *nums, int len)
{
	int max_num = 0;
	for (int i = 0; i < len; i++)
	{
		//获取数组的最大值
		if (nums[i] > max_num)
		{
			max_num = nums[i];
		}
	}
	max_num++;
	int *temp = new int[max_num];
	//memset(temp,0,sizeof temp);	//不知道为什么不行
	//初始化数组
	for (int i = 0; i < max_num; i++)
	{
		temp[i] = 0;
	}
	for (int i = 0; i < len; i++)
	{
		//将出现的次数存入数组中
		temp[nums[i]]++;
	}
	int index = 0;
	for (int i = 1; i < max_num; i++)
	{
		//出现的次数不为0时,将下标存入返回的数组中
		while (temp[i]--)
		{
			nums[index++] = i;
			
		}
	}
	delete[] temp;
}

9、桶排序

        桶排序的思想就是先计算出原数组的最大值和最小值的差值,然后分成若干个相同间距的区间,然后将原数组的值落在相应的区间中进行排序,最后组合起来。

暂未实现只用数组版本,后续写出来了再补上

10、基数排序

        先找出最大的位数,然后依次从最小位取余开始比较排序,直到比较到最大位数。

//基数排序
int getMaxDigital(int *nums, int len)
{
	int res = 1;
	int temp = 10;
	for (int i = 0; i < len; i++)
	{
		while (nums[i] >= temp)
		{
			temp *= 10;
			res++;
		}
	}
	/*cout << "max:" << res << endl;*/
	return res;
}
void radix_sort(int *nums, int len)
{
	int maxNum = getMaxDigital(nums, len);
	int *temp = new int[len];
	int start[10] = {0};		//记录每个数的前面的总个数+1也就是每个位置的起始值
	int count[10] = {0};		//记录每个位置(1-9)的个数
	int base = 10;
	while (maxNum--)
	{
		for (int i = 0; i < len; i++)
		{
			//先遍历一遍,取出当前位数并且记录个数在count中
			count[nums[i] / base % 10]++;
		}
		for (int i = 1; i < 10; i++)
		{
			//记录每个位数上1-9的起始下标
			start[i] = count[i - 1] + start[i - 1];
		}
		for (int i = 0; i < len; i++)
		{
			//根据每个数的位数上的值排序
			int index = nums[i] / base % 10;
			temp[start[index]++] = nums[i];
		}
		//排序好的值赋值给nums进行下个位数的循环
		for (int i = 0; i < len; i++)
		{
			nums[i] = temp[i];
		}
		base *= 10;
	}

}

总结

本人是个菜鸟,上述的一些算法都没有进行理论的分析、时间/空间复杂度的分析以及稳定的分析,代码写的也不是很严谨,没有进行一些特殊情况的判断。如有错误请大佬勿喷。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hard-coding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值