栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

三百行代码实现常用的六大排序算法

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

三百行代码实现常用的六大排序算法

七大排序算法
  • 1.前言
  • 2.内容
  • 3.总结
  • 4.更新日志

1.前言

2022.5.15 总结整理了之前学的排序算法的实现
语言选择的是C++
(计数排序太水了,没有整理,基数排序自认为学的不太扎实,后续可能会补)
(蒟蒻,轻喷,欢迎指正)

2.内容
#define _CRT_SECURE_NO_WARNINGS 1

#include 
using namespace std;
#include 
#include 
#include   //随机初始化
#include  

void BubbleSort(vector&b, int n)    //用&来修改数组 //从小到大排序
{
	1.从前向后冒泡
	//for (int i = 0; i < n - 1; i++)  //趟数n-1
	//{
	//	for (int j = 0; j < n - i - 1; j++)
	//		if (b[j] > b[j + 1])
	//			swap(b[j], b[j + 1]);
	//}

	2.将i条件倒序,更易理解
	//for (int i = n - 1; i > 0; i--)
	//{
	//	for (int j = 0; j < i; j++)
	//		if (b[j] > b[j + 1])
	//			swap(b[j], b[j + 1]);
	//}


	从后向前呢  //不可!!
	//for (int i = 0; i < n - 1; i++)
	//{
	//	for (int j = n-i-1; j > 0; j--)
	//	{
	//		if (b[j-1] > b[j])
	//			swap(b[j-1], b[j]);
	//	}
	//}
}

void SelectSort(vector & b, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		for (int j = i+1; j < n; j++)
		{
			if (b[j] < b[i])
				swap(b[j], b[i]);
		}
	}
}

void InsertSort(vector & b, int n)   //将待插入的元素插入已排好序的序列中,其余元素后移
{
	//小细节:先判断j>0,否则b[j-1]越界访问!!

	1.先找到合适的插入位置,再插入
	//for (int i = 1; i < n; i++)  //待插入元素下标
	//{
	//	int temp = b[i];
	//	int j = i;
	//	while (j > 0 && temp < b[j-1])  //不越界,并且符合后移条件
	//	{
	//		b[j] = b[j-1];  //后移
	//		j--;
	//	}
	//	b[j] = temp; //插入
	//}

	1.1改成for循环
	//for (int i = 1; i < n; i++)
	//{
	//	int temp = b[i];
	//	int j = i;
	//	for (j = i;j > 0&&b[j - 1] > temp; j--)
	//		b[j] = b[j - 1];
	//	b[j] = temp;    
	//}

	2.边插入边遍历
	//for (int i = 1; i < n; i++)
	//{
	//	int j = i;
	//	while (j > 0 && b[j] < b[j - 1])
	//	{
	//		swap(b[j], b[j - 1]);
	//		j--;
	//	}
	//}
	2.1改成for循环   //简洁
	//for (int i = 1; i < n; i++)
	//{
	//	for (int j = i; j > 0 && b[j - 1] > b[j];j--)
	//		swap(b[j - 1], b[j]);
	//}
}

void Partition(vector & c, int L, int M, int R)   //归并排序的合并过程
{
	//开辟一个额外数组,存储排序后的数组
	vector  ex(R - L + 1);   
	//左右指针
	int l = L;     
	int r = M + 1;
	int k = 0;    //额外数组
	//进行比较,并放入额外数组中
	while (l <= M && r <= R)   //左右指针不越界
	{
		ex[k++] = c[l] <= c[r] ? c[l++] : c[r++];    //先拷贝小的(若相等,先拷贝左边的)
	}
	//拷贝剩下的元素
	while (l <= M)
	{
		ex[k++] = c[l++];
	}
	while (r <= R)
	{
		ex[k++] = c[r++];
	}
	//重新放进原数组中
	int i = 0;
	for (const auto& e : ex)
		c[L + i++] = e;
}
void Guibingdg(vector & b, int L, int R)  //递归版本
{
	if (L >= R)
		return;
	else
	{
		int M = L + ((R-L) >> 1);   //中间位置
		Guibingdg(b, L, M);   //左有序
		Guibingdg(b, M + 1, R); //右有序
		Partition(b, L, M, R);   //合并
	}
}

void Guibingfdg(vector& b,int n)  //非递归版本(迭代  分而治之)
{
	vector  c(n);    //申请额外空间
	
	for (int segment = 1; segment < n; segment *= 2)   //划分部分表示每一步的步长(注意不要多加;)
	{
		for (int begin = 0; begin < n; begin +=segment* 2)
		{
			int L = begin, M = min(begin + segment, n), R = min(begin + segment * 2, n);   //定义L  M  R,划分范围
			int k = L;
			int p1 = L, end1 = M;
			int p2 = M, end2 = R;
			while (p1 < end1 && p2 < end2)   //不越界  (不加等号是因为后面的分治会考虑进去)
			{                                //同时符合最后一步 ==len时
				c[k++] = b[p1] < b[p2] ? b[p1++] : b[p2++];   //将小的先拷贝
			}
			//拷贝剩余元素
			while (p1 < end1)
				c[k++] = b[p1++];
			while (p2 < end2)
				c[k++] = b[p2++];
		}
		//将排序好的c中元素重新拷贝回b中
		for (int i = 0; i < n; i++)
			b[i] = c[i];
	}
}

void heapify(vector & c, int i, int heapsize)
{
	int left = 2 * i + 1;
	while (left < heapsize)
	{
		//找到左右孩子中最大的
		int largest = left + 1 < heapsize && c[left + 1] > c[left] ? left + 1 : left;
		//再与父亲比较
		largest = c[i] > c[largest] ? i : largest;
		//如果父节点已经最大,则不用下沉
		if (largest == i)
			break;
		//否则,先下沉,再继续
		swap(c[largest], c[i]);
		i = largest;
		left = 2 * i + 1;
	}
}
void Duipai(vector & b, int n)
{
	//if (n < 1)
	//	return;
	if (n >= 1)
	{
		//令数组变为大根堆
		for (int i = n - 1; i >= 0; i--)
			heapify(b, i, n);
		int heapsize = n;
		//交换之后,尾节点为最大值
		swap(b[0], b[--heapsize]);
		//重复此过程
		while (heapsize > 0)
		{
			//前面已经保证整个数组为大根堆,之后只需保证0~heapisize为大根堆即可
			heapify(b, 0, heapsize);

			swap(b[0], b[--heapsize]);
		}
	}
}

vector  part(vector & c, int L, int R)
{
	//设置左右指针
	int l = L - 1;
	int r = R;
	//index从L开始,直至遇到右指针
	int index = L; 
	while (index
		//小于则,左边界扩张,并且index后移
		if (c[index] < c[R])
			swap(c[++l], c[index++]);
		//大于则,右边界扩张,但index不后移,因为不确定交换过去的数字与c[R]的关系,需要在下一次的循环中判断
		else if (c[index] > c[R])
			swap(c[--r], c[index]);
		//相等则,先跳过
		else
			index++;
	}
	//将大于区的第一个和c[R]交换
	swap(c[r], c[R]);
	//将==区域的左边界和右边界传回去
	vector  d(2);
	d[0] = l + 1;
	d[1] = r;
	return d;
}
void QuickSortdg(vector & b, int L, int R)
{
	if (L < R)
	{
		//在L..R上随机选择一个数,作为划分值
		int ret = L + rand() % (R - L + 1);
		swap(b[ret], b[R]);
		//part函数进行分层
		vector  d = part(b, L, R);
		//利用传回来的边界,继续递归(==区域的数字不用再排序了)
		QuickSortdg(b, L, d[0] - 1);   // < 区域
		QuickSortdg(b, d[1] + 1, R);   // > 区域
	}
}

int main()
{
	srand((unsigned int)time(0));
	int n;
	n=rand()%10+5; //数组大小在 5~14
	vectora(n);    //创建动态数组对象a
	for (int i = 0; i < n; i++)
		a[i] = rand()%10000-5000;       //随机-5000~4999
	for (const auto& e : a)   //排序前先输出,做对比
		cout << e << " ";
	cout << endl;
//	BubbleSort(a, n);  
//	SelectSort(a, n);
//	InsertSort(a, n);
//	Guibingdg(a, 0, n - 1);   //递归版本的归并排序
//	Guibingfdg(a, n);        //迭代版本的
//	Duipai(a,n);
//	QuickSortdg(a, 0, n - 1);
//	QuickSortfdg();
	for (const auto& e : a)   //范围for语句,遍历输出
		cout << e << " ";
	return 0;
}
//5.15完美的一天~~

3.总结

最重要的是理解它们的思想

4.更新日志

2022.5.15 整理上传

欢迎催更~
欢迎评论留言、指正~~

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/886471.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号