经典排序查找算法(c++版本)

冒泡排序

冒泡排序是最最基础的一个排序方法
重复走访相邻的元素,一次比较两个,如果顺序不符合要求就返过来
算法复杂度O(N^2)

vector<int> bubbleSort(vector<int> nums) {
	for (int i = 0; i < nums.size(); i++) {
		for (int j = 0; j < nums.size() - 1 -i; j++) {
			if (nums[j] > nums[j + 1]) {
				int temp = nums[j];
				nums[j] = nums[j+1];
				nums[j + 1] = temp;
			}
		}
	}
	return nums;
}

基本思想:

在一个序列中,从前往后两两数之间依次进行比较,让较大的数向后移动 ,较小的数字向上移动
如果其与我们想要的方向相反 就将两个数字进行交换

优缺点:
优点:稳定
缺点:慢,每次只能移动两个相邻的数据

选择排序

选择排序也是两层循环
自我感觉和冒泡排序有些许相似的地方
选择排序是从开始的位置
依次找当前位置之后所有元素的最小值
然后和当前位置的元素交换

vector<int> selection_sort(vector<int>nums) {
	for (int i = 0; i < nums.size() - 1; i++) {
		int mins = i;//i之后最小的索引
		for (int j = i + 1; j < nums.size(); j++) {
			if (nums[mins] > nums[j]) {
				mins = j;//更换索引
			}
		}
		swap(nums[i], nums[mins]);
	}
	return nums;
}

基本思想

每次遍历当前元素之后所有的元素 选出最小值 与当前元素进行交换
直至元素遍历完毕

插入排序

插入排序是遍历一次数组
从索引为1开始
每当遍历一个数字的时候,就把这个数字按照顺序插入到前面已经排序的数组中

vector<int> insert_sort(vector<int> nums) {
	for (int i = 1; i < nums.size(); i++) {
		int key = nums[i];
		int j = i - 1;
		while (j >= 0 && key < nums[j]) {
			nums[j + 1] = nums[j];//向后移一位
			j--;
		}
		nums[j+1] = key;
	}
	return nums;
}

基本思想:
将一个记录插入到已经排序完好的有序表中,从而得到一个新的有序表

优缺点:
优点:稳定,快
缺点:比较次数不一定,比较次数越少,插入点之后的元素越多

快速排序

快排用到了分治的思想
我们声明两个指针分别指向数组首尾
然后我们声明一个临时变量 遍历数组
将临时变量放于合适的位置
使得该变量的左右 左边都是小于该数 右边都大于该数

然后递归求解

int Paritition1(vector<int> & A, int low, int high) {
	int pivot = A[low];
	while (low < high) {
		while (low < high && A[high] >= pivot) {
			--high;
		}
		A[low] = A[high];
		while (low < high && A[low] <= pivot) {
			++low;
		}
		A[high] = A[low];
	}
	A[low] = pivot;
	return low;
}

void QuickSort(vector<int> & A, int low, int high) //快排母函数
{
	if (low < high) {
		int pivot = Paritition1(A, low, high);
		QuickSort(A, low, pivot - 1);
		QuickSort(A, pivot + 1, high);
	}
}

主要思想:

选择一个基准元素(升序排序),比基准元素小的放于基准元素之前,相反放于基准元素之后
然后在将小于基准值的元素子数列和大于基准值的子序列 分别按照原来的方法排序

优缺点:
优点:顾名思义 非常快,移动数据较少
缺点:不稳定
在数据越乱的时候 效率越高,如果其有序的时候,会近似冒泡排序

效率:
如果每次选到的元素都是中间位置的元素(恰好将数组分为大小相等的两块)
时间复杂度为O( nlogn ) 空间复杂度为O( logn )
如果每次都是选到最大、最小的情况下 效率为O(n^2) 近似于冒泡排序空间复杂度为O(n)

归并排序

归并排序同快速排序一样,都是分治思想的代表
我们把原问题分解成为多个子问题,然后对子问题求解 最后构造出原问题的解

void  merge(vector<int>& nums, int left, int mid, int right) {
	int i = left;
	int j = mid + 1;
	int index = 0;
	vector<int> ans(right - left + 1);
	while (i <= mid && j <= right) {
		ans[index++] = nums[i] < nums[j] ? nums[i++] : nums[j++];
	}
	while (i <= mid) ans[index++] = nums[i++];
	while (j <= right) ans[index++] = nums[j++];
	for (int i = 0; i < index; i++) {
		nums[left + i] = ans[i];
	}
}
void merge_sort(vector<int>& nums, int left, int right) {
	if (left >= right)return;

	int mid = left + (right - left) / 2;
	merge_sort(nums, left, mid);
	merge_sort(nums,mid + 1, right);
	merge(nums, left, mid, right);

}

主要思想:
将一个完整的数组 分成一般 一次递归下去 直至成为包含两个或者一个的小数组
将其按想要的顺序两两交换
然后在将其组合起来

顺序查找

int search(vector<int>& nums, int target) {
	for (int i = 0; i < nums.size(); i++) {
		if (nums[i] == target) {
			return i;
		}
	}
	return -1;
}

二分查找

二分查找的思想和分治法差不太多
元素必须是有序的,如果是无序的则要先进行排序操作。
最坏情况下,关键词比较次数为log2(n+1),且期望时间复杂度为O(log2n);

非递归

int search(vector<int>& nums, int target) {
	int left = 0;
	int right = nums.size() - 1;
	int mid = left + (right - left) / 2;
	while (left < right) {
		mid = left + (right - left) / 2;
		if (nums[mid] < target) {
			left = mid + 1;
		}
		else if (nums[mid] > target) {
			right = mid - 1;
		}
		else {
			return mid;
		}
	}
	return -1;
}

递归

int search(vector<int>& nums, int target,int left,int right) {
	int mid = (left + right) / 2;
	if (target == nums[mid]) {
		return mid;
	}
	else if(target<nums[mid]){
		return search(nums, target, left, mid-1);
	}
	else {
		return search(nums, target, mid + 1, right);
	}
}

其他解法我也会陆续更新的
希望我所写的对大家有所帮助

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值