C++ 实现八大排序算法

记录并分享一下学习经验٩(^ᴗ^)۶

1.算法复杂度比较

 2.算法实现

以下实现排序均为由小到大,且传入均为vector<int>类型。

class Sort {
public:

	/* 插入排序
	*  遍历 并维护一个有序序列
	*  遍历到一个数据时进行与维护的有序序列比较
	*  大于 维护的有序序列的尾部(最大值)则不处理
	*  小于 维护的有序序列的尾部(最大值)则找到正确的位置插入
	*/
	void insertion_sort(vector<int>& arr){
		int n = arr.size();

		for (int i = 1; i < n; i++){
			int j = i;
			int temp = arr[i];
			while (j > 0 && temp < arr[j - 1]){
				arr[j] = arr[j - 1];
				j--;
			}
			arr[j] = temp;
		}
	}

	/* 希尔排序
	*  先分组 再插入排序 将数组变为“基本有序”的状态
	*  插入排序 plus版 插入排序在处理“基本有序”的数组时效率很高
	*/
	void shell_sort(vector<int>& arr){
		int n = arr.size();

		int h = 1;
		while (h < n / 3) {
			h = 3 * h + 1;
		}

		while (h >= 1) {
			for (int i = h; i < n; i++) {
				for (int j = i; j >= h && arr[j] < arr[j - h]; j -= h) {
					swap(arr[j], arr[j - h]);
				}
			}
			h = h / 3;
		}
	}


	/* 选择排序
	*  遍历 找到最大元素 放到尾部
	*/
	void selection_sort(vector<int>& arr){
		int n = arr.size();

		for (int i = 0; i < n; i++){
			int minIndex = i;
			for (int j = i + 1; j < n; j++){
				if (arr[j] < arr[minIndex]){
					minIndex = j;
				}
			}
			swap(arr[i], arr[minIndex]);
		}
	}


	/* 堆排序
	*  类似完全二叉树的结构
	*  每次找到最大值 并且维持树的结构 最后将最大值放到队尾
	*/
	void heap_sort(vector<int>& arr){
		int n = arr.size();
		//初始化顶堆
		for (int i = n / 2 - 1; i >= 0; i--){
			Heap_helper(arr, i, n - 1);
		}
		//最顶上的一定为最大
		for (int i = n - 1; i > 0; i--) {
			//将最大的元素放到未排序序列的尾部
			swap(arr[0], arr[i]);
			//维护顶堆结构
			Heap_helper(arr, 0, i - 1);
		}
	}
	void Heap_helper(vector<int>& arr, int l, int r){
		//父节点与子节点在数组中的位置
		int dad = l;
		int son = dad * 2 + 1;

		while (son <= r) {
			//选择较大的子节点
			if (son + 1 <= r && arr[son] < arr[son + 1])
				son++;
			//父节点最大则返回
			if (arr[dad] > arr[son])
				return;
			else { //子节点大 则交换节点 继续往下
				swap(arr[dad], arr[son]);
				dad = son;
				son = dad * 2 + 1;
			}
		}
	}


	/* 冒泡排序
	*  比较相邻元素,不是预期大小则交换
	*/
	void bubble_sort(vector<int>& arr){
		int n = arr.size();

		int sign;
		for (int i = 0; i < n; i++){
			sign = 1;
			for (int j = 1; j < n - i; j++){
				if (arr[j] < arr[j - 1]){
					swap(arr[j], arr[j - 1]);
					sign = 0;
				}
			}
			if (sign)break;
		}
	}

	
	/* 快速排序
	*  在数组找一个“基准”比它大的放在它前面 比它小的放在它后面
	*/
	void quick_sort(vector<int>& arr){
		int n = arr.size();

		Quick_helper(arr, 0, n - 1);
	}
	void Quick_helper(vector<int>& arr, int l, int r){
		if (l >= r)
			return;
		int mid = arr[r];
		int left = l, right = r - 1;
		while (left < right) {
			while (arr[left] < mid && left < right)
				left++;
			while (arr[right] >= mid && left < right)
				right--;
			swap(arr[left], arr[right]);
		}
		//判断中间的属于那一边
		if (arr[left] >= arr[r])
			swap(arr[left], arr[r]);
		else
			left++;

		Quick_helper(arr, l, left - 1);
		Quick_helper(arr, left + 1, r);
	}


	/* 归并排序
	*  分治法 先分成小组 保证小组内有序 再将小组与小组合并
	*/
	void merge_sort(vector<int>& arr){
		int n = arr.size();

		Merge_Sort(arr, 0, n - 1);
	}
	void Merge_Sort(vector<int>& arr, int l, int r){
		if (l == r){
			return;
		}
		else {
			int m = (l + r) / 2;
			Merge_Sort(arr, l, m);
			Merge_Sort(arr, m + 1, r);
			Merge_helper(arr, l, m, r);
		}
	}
	void Merge_helper(vector<int>& arr, int l, int m, int r){
		vector<int> temp = vector<int>(r - l + 1);
		//l-m是前一半 m-r是后一半 两半均为有序 以下实现合并两个有序数组
		int k = l, i = l, j = m + 1;
		while (i <= m && j <= r){
			if (arr[i] <= arr[j]){
				temp[k++] = arr[i++];
			}
			else{
				temp[k++] = arr[j++];
			}
		}

		//有一半已经排序完 将另一半剩下的补上
		while (i <= m) temp[k++] = arr[i++];
		while (j <= r) temp[k++] = arr[j++];

		for (int i = l; i<k; i++){
			arr[i] = temp[i];
		}
	}



	/* 基数排序
	*  按数位排序
	*/
	void radix_sort(vector<int>& arr){
		int n = arr.size();
		//求出最高位
		int d = Radix_helper(arr);
		
		vector<int> temp(n);
		
		//count用来记录数组在某位上0~9分别的数量
		vector<int> count(10, 0);
		int i, j, k;
		int radix = 1;
		//按位排序 
		for (i = 1; i <= d; i++){
			//计数器清零
			count = vector<int>(10, 0);

			for (j = 0; j < n; j++){
				k = (arr[j] / radix) % 10;
				count[k]++;
			}
			for (j = 1; j < 10; j++){
				//累加 方便在对应的位置存放数据
				count[j] = count[j - 1] + count[j];
			}
			for (j = n - 1; j >= 0; j--){
				//把数组按照 当前位 的大小排序
				k = (arr[j] / radix) % 10;
				temp[count[k] - 1] = arr[j];
				count[k]--;
			}
			arr = temp;
			//下一位
			radix = radix * 10;
		}

	}
	int Radix_helper(vector<int>& arr){
		int n = arr.size();
		//先找到最大值 再求最大位数
		int maxData = arr[0];
		for (int i = 1; i < n; ++i)
		{
			if (maxData < arr[i])
				maxData = arr[i];
		}

		int d = 1;
		int p = 10;
		while (maxData >= p)
		{
			maxData /= 10;
			++d;
		}
		return d;
	}

};

1.0 十大经典排序算法 | 菜鸟教程 (runoob.com)icon-default.png?t=LA92https://www.runoob.com/w3cnote/ten-sorting-algorithm.html这里面有每个排序的动画,可以参考一下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值