八大排序算法(C++)

一,冒泡排序

先说结论,该排序算法在实践中没有意义,但是对初学者有较好的教学意义

该算法时间复杂度为O(N*2)   空间复杂度为O(1)

最好情况下时间复杂度为O(N)当数据原本是有序时

代码实现

//冒泡排序
void bulleSort(int* a,int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int falg = 1;//给一个状态值
		for (int j = 0; j < n-i-1; j++)
		{
			if (a[j] > a[j+1])
			{
				swap(a[j], a[j+1]);
				falg = 0;//如果初始位置不是有序的就将状态值改为0
			}
		}
		if (falg == 1)//如果状态值为1则说明已经有序了
		{
			break;
		}
	}
}

二,选择排序

时间复杂度和空间复杂度与冒泡排序一样,在实际也是没有很大意义

代码实现

void selectSort(int* a, int n)
{
	int left = 0, right = n - 1;//定义左右边界
	
	for (int i = 1; i <= right; i++)
	{
		int max = left, min = left;
		for (int j = left; j <= right; j++)
		{
			if (a[min] > a[j])//找到当前范围最小值下标
			{
				min = j;
			}
			if (a[max] < a[j])//找到当前范围最大值下标
			{
				max = j;
			}
		}
		swap(a[left], a[min]);//将最小值交换到最左边
		if (max == left)//如果当前最大值的下标刚好为left,此时需要更新max
		{
			max = min;
		}
		swap(a[right], a[max]);//将最大值交换到最右边
		left++;
		right--;
	}	
}

三,插入排序

时间复杂度:O(N*2)

空间复杂度:O(1)

最好情况下:O(N)当数组已经是有序的时候


void insertSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int end = i;
		int tem = a[end + 1];
		while (end >= 0)
		{
			if (tem < a[end])//如果后面的小于前面的就交换位置
			{
				swap(a[end], a[end + 1]);
				--end;
			}
			else
			{
				break;
			}
		}
		a[end + 1] = tem;//将tem值放入对应位置
	}
	
}

四,希尔排序

时间复杂度:O(N*1.3)

空间复杂度:O(1)

原理:先进行预排序将数组尽量排成有序状态,最后再进行插入排序时就非常快,预排序的实质其实也是插入排序,只不过每次交换的位置有所不同,主包也讲不清楚,需要具体了解的阔以去看看其他优秀的博主,O(∩_∩)O哈哈~

void shellsort(int* a, int n)
{
	int ret = n;
	while (ret > 1)
	{
		ret = ret / 3 + 1;
		//需要进行预排序,预排序实质上就是插入排序,只不过交换的位置有所不同
		for (int i = 0; i < n - ret; i+=ret)
		{
			int end = i;
			int tem = a[end + ret];
			while (end >= 0)
			{
				if (tem < a[end])//如果后面的小于前面的就交换位置
				{
					swap(a[end], a[end + ret]);
					end-= ret;
				}
				else
				{
					break;
				}
			}
			a[end + ret] = tem;//将tem值放入对应位置
		}
	}
}

五,堆排序

时间复杂度:O(N*logN)

空间复杂度:O(1)

原理:先建堆,排升序建大堆排降序建小堆

        通过向下调整法将数组建成堆序,向下调整法是通过父亲与较大的孩子比较,如果父亲比孩子小则交换两者位置,直至向下将孩子比较完

        将数组看成是多个堆,依次比较完就变成了大堆

//向下调整法
void AdjustDown(int* a, int parent,int n)
{
	int child = parent * 2+1;
	while (child < n)
	{
		if (child + 1 < n && a[child] < a[child + 1])//如果右孩子大于左孩子
		{//需要注意右孩子的下标不能大于等于n,否则会造成越界
			child++;
		}
		if (a[parent] < a[child])
		{
			swap(a[parent], a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
void heapSort(int* a, int n)
{
	
	for (int i = n/2-1; i >=0; i--)//(n-2)/2 定位到最后一个结点的父亲节点
	{
		AdjustDown(a, i, n);//向下调整建大堆
	}

	for (int i = n-1; i >=0; i--)
	{
		swap(a[i], a[0]);
		AdjustDown(a, 0, i);
	}
}

六,归并排序

时间复杂度:O(N*logN)

空间复杂度:O(N)

原理

归并排序采用分治法

  1. 分解:将数组递归分成两半,直到子数组长度为1。

  2. 合并:将两个有序的子数组合并成一个有序数组。

//归并排序
void mergeSort(int* a, int begin, int end)
{
	if (begin >= end)
		return;
	int mid = (begin + end) / 2;
	int begin1 = begin, end1 = mid;
	int begin2 = mid+1, end2 = end;
	mergeSort(a, begin1, end1);//左
	mergeSort(a, begin2, end2);//右
	// 合并逻辑
	int* tmp = new int[end - begin + 1]; // 临时数组存储合并结果
	int i = begin1;                     // 左子数组指针
	int j = begin2;                     // 右子数组指针
	int k = 0;                          // 临时数组指针

	// 比较并合并两个有序子数组
	while (i <= end1 && j <= end2) {
		if (a[i] <= a[j])
			tmp[k++] = a[i++];
		else              
			tmp[k++] = a[j++];
	}

	// 处理剩余元素
	while (i <= end1) 
		tmp[k++] = a[i++];
	while (j <= end2) 
		tmp[k++] = a[j++];

	// 将合并结果拷贝回原数组
	for (int m = 0; m < k; m++) {
		a[begin + m] = tmp[m];
	}

	delete[] tmp;
}

七,计数排序

时间复杂度:O(N+k)

空间复杂度:O(K)

计数排序的核心思想是通过统计元素频次直接确定元素的位置,无需比较。具体步骤如下:

1. 确定数据范围

遍历数组,找到最大值 max 和最小值 min,计算范围 k = max - min + 1

2. 统计频次

创建长度为 k 的计数数组 tem[],统计每个元素出现的次数。

例如,元素 a[i]对应 tem[a[i]-min]++

3.将取到的值按顺序复制到原数组
//计数排序
void jishuSort(int* a, int n)
{
	//1.找到数组中的最大最小值
	int max = a[0], min = a[0];
	for (int i = 0; i < n; i++)
	{
		if (a[i] > max)
		{
			max = a[i];
		}
		if (a[i] < min)
		{
			min = a[i];
		}
	}

	int k = max - min + 1;
	int* tem = new int[k]();//创建数组并初始化为0

	for (int i = 0; i < n; i++)
	{
		tem[a[i]-min]++;//a[i]-min 将a的值映射到tem;
	}

	int j = 0;
	for (int i = 0; i < k; i++)
	{
		while (tem[i]--)
		{
			a[j++] = i + min;
		}
	}
	delete[] tem;
}

八,快速排序

快排实现   在主包的另一篇文章中有讲到

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小新学编程Pro版

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

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

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

打赏作者

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

抵扣说明:

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

余额充值