寒假训练营 第七节 基础算法(二)总结

本文介绍了两种经典的排序算法:快速排序和归并排序。快速排序是基于冒泡排序的递归分治法,通过一趟排序将序列分成两部分,再分别进行排序。归并排序则是通过不断合并有序子表来达到整体有序。此外,文章还提到了二分查找的原理和适用场景,强调了它对数据有序性和存储结构的要求。
摘要由CSDN通过智能技术生成
/*
快速排序:是从冒泡排序算法演变而来的,实际上是在冒泡排序基础上的递归分治法。
它是通过一趟排序将待排序的记录分割成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,
则可以分别对这两部分记录继续进行排序,以达到整个序列有序。
模板如下:
*/
void quickSort(int* arr, int L, int R)
{
 	if (L > R) return;
 	int left = L, int right = R;

 	int pivot = arr[left];
 	while (left < right){
 		while (left < right && arr[right] >= pivot) {
 			right--;
 		}
 		if (left < right) {
 			arr[left] = arr[right];
 		}
 		while (left < right && arr[left] <= pivot) {
 			right--;
 		}
 		if (left < right) {
 			arr[right] = arr[left];
 		}
 		if (left >= right) {
 			arr[left] = pivot;
 		}
 	}
 	quickSort(arr, L, right - 1);
 	quickSort(arr, right + 1, R);

}

归并排序

所谓归并是指两个或两个以上的有序表合并成一个新的有序表。

  • 思路:
    1、将n个记录的待排序序列看成是有n个长度都为1的有序子表组成。
    2、将两两相邻的子表归并为一个有序子表。
    3、重复上述步骤,直至归并为一个长度为n的有序表。2.归并排序过程示例
    在这里插入图片描述
代码实现:
#include <bits/stdc++.h >
using namespace std;
void merge(int* a, int low, int mid, int hight)  //合并函数
{
	int* b = new int[hight - low + 1];  //用 new 申请一个辅助函数
	int i = low, j = mid + 1, k = 0;    // k为 b 数组的小标
	while (i <= mid && j <= hight)  
	{
		if (a[i] <= a[j])
		{
			b[k++] = a[i++];  //按从小到大存放在 b 数组里面
		}
		else
		{
			b[k++] = a[j++];
		}
	}
	while (i <= mid)  // j 序列结束,将剩余的 i 序列补充在 b 数组中 
	{
		b[k++] = a[i++];
	}
	while (j <= hight)// i 序列结束,将剩余的 j 序列补充在 b 数组中 
	{
		b[k++] = a[j++];
	}
	k = 0;  //从小标为 0 开始传送
	for (int i = low; i <= hight; i++)  //将 b 数组的值传递给数组 a
	{
		a[i] = b[k++];
	}
	delete[]b;     // 辅助数组用完后,将其的空间进行释放(销毁)
}
void mergesort(int* a, int low, int hight) //归并排序
{
	if (low < hight)
	{
		int mid = (low + hight) / 2;
		mergesort(a, low, mid);          //对 a[low,mid]进行排序
		mergesort(a, mid + 1, hight);    //对 a[mid+1,hight]进行排序
		merge(a, low, mid, hight);       //进行合并操作
	}
}
int main()
{
	int n, a[100];
	cout << "请输入数列中的元素个数 n 为:" << endl;
	cin >> n;
	cout << "请依次输入数列中的元素:" << endl;
	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
	}
	mergesort(a, 0, n-1);
	cout << "归并排序结果" << endl;
	for (int i = 0; i < n; i++)
	{
		cout << a[i] << " ";
	}
	cout << endl;
	return 0;
}
效率分析:

对n个元素的序列,执行二路归并算法,则必须做 log2n趟归并,每一趟归并的时间复杂度是O(n),所以二路归并的时间复杂度为O( l o g 2 n log_2n log2n)
两路归并排序需要和待排序序列一样多的辅助空间。其空间复杂度为O(n)。
两路归并排序也是一种稳定性的排序。

二分查找

也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

基本思路:

在有序表中,取中间元素作为比较对象,若给定值与中间元素的关键字相等,则查找成功;若给定值小于中间元素的关键字,则在中间元素的左半区继续查找;若给定值大于中间元素的关键字,则在中间元素的右半区继续查找。不断重复上述查找过程,直到查找成功,或所查找的区域无数据元素,查找失败。

主要步骤:

1、置初始查找范围:low=1,high=n(设置初始区间)
2、求查找范围中间项:mid=(low+high)/2(取中间点位置)
3、将指定的关键字值k与中间项的关键字比较:

  • 若相等,查找成功,找到的数据元素为此时mid指向的位置;
  • 若k小于中间项关键字,查找范围的低端数据元素指针low不变,高端数据元素指针high 更新为mid-1;

4、重复步骤2、3直到查我成功或查找范围为空(low>high),即查找失败为止。
5、如果查找成功,返回找到元素的存放位置,即当前的中间项位置指针mid;否则返回查找失败标志。
在这里插入图片描述

代码实现:
#include<iostream>
using namespace std;
int a[100];
int binary_scarch(int a[],int len,int e){
	int left=0;
	int right=len;
	int mid;
	while(left<=right){
		int mid=(left+right)/2;
		if(a[mid]>e){
			right=mid-1;
		}else if(a[mid]<e){
			left=mid+1;
		}else{
			return mid;
		}
	}
	return -1;
}
int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++)
	cin>>a[i];
	int e;
	cin>>e;
	cout<<binary_scarch(a,n-1,e);
}

二分查找它充分利用了元素间的次序关系,采用分治策略,可在最坏的情况下用O(log n)完成搜索任务。
优点:比较次数少,查找速度快,平均性能好 ,占用系统内存较少
缺点:待查表为有序表,插入删除困难

  • 二分查 找依赖的是顺序表结构,也就是数组,需要能够按照下标随机访问元素
  • 二分查找针对的是有序数据,如果数据无序,需要先进行排序。而如果有频繁的插入、删除操作,则每次查找前都需要再次排序,这时候,二分查找将不再适用。
  • 数据量太大或是太小都不适合用二分查找。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值