【C++】十大经典排序算法 代码及思路

文章展示了如何利用LeetCode的第88题来验证C++实现的几种排序算法的正确性,包括冒泡排序、插入排序、归并排序、快速排序、希尔排序、选择排序和堆排序。每种排序算法的时间复杂度和稳定性也进行了说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

可用leetcode第88题来验证自己所写的排序算法是否正确
88. 合并两个有序数组

代码如下:
注意,以下版本是在vs上进行编写的,写88题时需要先将nums2的数组元素复制到nums1数组的后半段,再调用这些排序函数

using namespace std;
# include<iostream>
# include<vector>


//打印数据
void print_vec(const vector<int>& vec) {
	for (auto it = vec.begin(); it != vec.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}

// 冒泡排序 稳定排序  时间复杂度O(n*n),空间复杂度O(1)
void bubbleSort(vector<int>& vec) {
	// 两两比较
	int n = vec.size();
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n - i - 1; j++) {
			if (vec[j] > vec[j + 1]) swap(vec[j], vec[j + 1]);
		}
	}
}


// 插入排序 稳定排序  时间复杂度O(n*n),空间复杂度O(1)
void insertSort(vector<int>& vec) {
	// 每次将新元素插入到已排序的有序队列里面
	int n = vec.size();
	for (int i = 1; i < n; i++) {
		if (vec[i] > vec[i - 1]) continue;
		int temp = i;//记录新元素每次交换后的位置
		for (int j = i - 1; j >= 0; j--) {

			if (vec[temp] < vec[j]) {//只要比排序数小,就交换两者位置
				swap(vec[temp], vec[j]);
				temp = j;//记录新元素的位置
			}
			else break;
		}

	}
}


//归并排序 稳定排序 时间复杂度O(n*logn),空间复杂度O(n)
//算法思想
//1、把长度为n的输入序列分成两个长度为n / 2的子序列;
//2、对这两个子序列分别采用归并排序;
//3、 将两个排序好的子序列合并成一个最终的排序序列。
void mergeSort(vector<int>& vec,vector<int> &data,int start,int end) {
	//vec为需要排序的数组,data为放置排序好的子序列的数组,取闭区间[start,end]
	if (start >= end) return;
	int mid = start + (end - start) / 2;
	mergeSort(vec, data, start, mid);
	mergeSort(vec, data, mid + 1, end);

	//p1为前半个数组的头指针,p2为后半个数组的头指针,p为data数组的头指针
	int p1 = start, p2 = mid + 1, p = start;
	//int len = (end - start) * 2;
	for (; p <= end; p++) {
		//这里用if进行判断的时候很重要,容易把情况漏掉
		//刚开始我写成if(p1<=mid&&vec[p1]<vec[p2]){} else{}  ,这样写漏掉了一些情况
		if (p1<=mid&&p2>end) {
			data[p] = vec[p1++];
		}
		else if(p1>mid&&p2<=end){
			data[p] = vec[p2++];
		}
		else {//两个都没越界
			data[p] = vec[p1] > vec[p2] ? vec[p2++] : vec[p1++];
		}
	}
	for (int i = start; i <= end; i++) {
		vec[i] = data[i];
	}

}


// 快速排序 不稳定排序  时间复杂度O(n*log n),空间复杂度O(logn)(递归会使用栈)
//1、选取第一个数为基准
//2、将比基准小的数交换到前面,比基准大的数交换到后面
//3、对左右区间重复第二步,直到各区间只有一个数
void quickSort(vector<int>& vec,int index_start,int index_end) {
	//使用递归 传入整个数组和需要处理的数据起始位置[index_start,index_end]
	
	if (index_end <= index_start) return;//递归终止条件

	int temp = index_start;//选取第一个数为基准
	for (int i = temp + 1; i <= index_end;i++ ) {
		if (vec[i] < vec[temp]) {
			for (int j = i; j > temp; j--) {
				//vec[i]依次和temp开始一直到i-1位置的数进行交换,直到i位置数字换到vec[temp]前面去
				swap(vec[j], vec[j - 1]);//两两交换
				
			}
			temp++;//记录基准数更新后的位置
		}

	}
	quickSort(vec, index_start, temp - 1);
	quickSort(vec, temp + 1, index_end);

}

// 希尔排序 不稳定排序  时间复杂度O(n*n),空间复杂度O(1)
// 插入排序的变种,局部有序
void insert_sort(vector<int>&vec, int gap,int start_index) {//将start_index插入到本组中正确的位置
	int insert_num = vec[start_index];
	int i = start_index - gap;
	for (; i >=0&&vec[i]>insert_num; i=i-gap) {
		vec[i + gap] = vec[i];
	}
	vec[i + gap] = insert_num;
}
void shellSort(vector<int>& vec) {
	
	for (int gap = vec.size() / 2; gap >= 1; gap /= 2) {
		for (int j = gap; j < vec.size(); j++) {
			insert_sort(vec, gap, j);
		}
	}


}

// 选择排序 不稳定排序  时间复杂度O(n*n),空间复杂度O(1)
void selectSort(vector<int>& vec) {
	//每次选择剩余元素里面的最小值放到第一个循环的位置上
	int n = vec.size();
	for (int i = 0; i < n; i++) {
		int minNum = i;
		for (int j = i + 1; j < n; j++) {
			if (vec[minNum] > vec[j]) minNum = j;;
		}
		swap(vec[i], vec[minNum]);
	}
}


// 堆排序 不稳定排序  时间复杂度O(n*logn),空间复杂度O(1)
//堆排序的基本思想是:
//将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。
//将其与末尾元素进行交换,此时末尾就为最大值。
//然后将剩余n - 1个元素重新构造成一个堆,这样会得到n个元素的次小值。
//如此反复执行,便能得到一个有序序列了
//void heapify(vector<int>& vec, int index) {
//
//}
void adjust_maxheap(vector<int>& vec,int end) {//调整为大顶堆
	//end为需要调整的最大位置,闭区间[0,end]
	//节点i的父节点:(i-1)/2  左孩子节点:2i+1,右孩子节点:2i+2

	for (int i = (end - 1) / 2; i >= 0; i--) {//(end-1)/2为倒数第二层的右边最后一个非叶子结点
		//其实就是每次选择非叶子结点和它的孩子节点为一组,
		//把这组节点的最大值找出来当做父节点,再从右往左,从下到上依次循环操作
		int left = 2 * i + 1;
		int right = 2 * i + 2;
		if (right > end) {
			//只有左孩子节点
			//这种情况最多出现一次
			if (vec[left] > vec[i]) {
				swap(vec[left], vec[i]);
			}
		}
		else {//两个孩子节点都有
			int index = vec[left] > vec[right] ? left : right;
			if (vec[index] > vec[i]) {
				swap(vec[index], vec[i]);
			}
		}

	}
}
void heapSort(vector<int>& vec) {
	for (int i = 0; i < vec.size()-1; i++) {
		adjust_maxheap(vec, vec.size()-1 - i);
		swap(vec[0], vec[vec.size() - 1 - i]);//把调整好的大顶堆的第一个值和end进行交换

	}
}


// 计数排序
void countSort(vector<int>& vec) {

}

int main() {
	vector<int> vec{ 10,8,4,6,9,10,123,6,2,14,3,8,5 };

	//cout << "------快速排序-------" << endl;
	//quickSort(vec,0,vec.size()-1);
	//print_vec(vec);

	//cout << "------归并排序-------" << endl;
	//vector<int> data(vec.size(), 0);
	//mergeSort(vec,data,0,vec.size()-1);
	//print_vec(data);

	cout << "------堆排序-------" << endl;
	heapSort(vec);
	print_vec(vec);

	return 0;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值