承接上一篇文章:C++十大排序学习笔记(二)_王必能会的博客-CSDN博客
一、快速排序
快速排序的基本思想原理分为以下三步:
1)先从数列中随机的取出一个数作为基准数,将其与最右边的数做交换(随机的取数,可以适当的降低时间复杂度);
2)扫描数列,将比基准数小的元素全部放在左边,等于基准数的元素放在中间,大于基准数的元素放在右边(注意:此时数列最右边的数是基准数,但是划分区间即小于, 等于, 大于时,暂不包括基准数。)区间分完后,再将基准数与大于区间的第一个数(有时也可以是等于区间的最后一个数的下一个数)做交换
3)然后再对小于区间和大于区间重复进行第一二步操作,直到各个区间少于两个元素,此时整个数组也就变成了有序数组。
代码如下:
#include <iostream>
using namespace std;
#include <vector>
#include<algorithm>
#include <math.h>
#include<cstdio>
#include<ctime> //要调用time(),需要加入头文件< ctime >
#define random_int_3(a,b) ((rand()%(b-a+1))+ a) //取得[a,b]的随机整数
void print(vector<int>& arr) {
for (int i = 0; i < arr.size(); i++) {
cout << arr[i] << endl;
}
}
//这是一个处理arr数组的函数 {3,5,6,7,4,3,5,8}
//默认以arr[r]做划分 划分为 <p ==p >p 以最右边的数作为划分值
//返回的是等于区域的左右边界,并且返回的必定是一个长度为2的数组res, 左res[0] 右res[1]
vector<int> partition(vector<int>& arr, int i, int right) {
int less = i-1; //小于区域的右边界
int more = right; //大于区域的左边界
while (i < more) {
if (arr[i] < arr[right]) {
swap(arr[i], arr[++less]);
i++;
}
else if (arr[i] > arr[right]) {
swap(arr[i], arr[--more]);
}
else {
i++;
}
}
swap(arr[more], arr[right]);
return { less+1, more };
}
void quickSort(vector<int> &arr, int left, int right) {
if (left < right) {
srand((int)time(0)); //利用系统时钟,产生不同的随机数种子,把0换成NULL也行
int r = random_int_3(left, right);
//int r = (rand() % (right - left + 1))+left;
swap(arr[r], arr[right]);
vector<int> res = partition(arr, left, right);
quickSort(arr, left, res[0]-1);
quickSort(arr, res[1]+1, right);
}
}
int main() {
vector<int> arr1 = {3,5,6,7,8,4,3,5,6,2,1,4};
quickSort(arr1, 0, arr1.size() - 1);
print(arr1);
return 0;
}
二、堆排序
堆排序是利用堆这种数据结构而设计的一种排序算法,堆具备以下特点:
1) 完全二叉树;(从上到下,从左到右,每一层的节点都是满的,最下一层所有节点都连续集中在最左边。)
2)二叉树每个结点的值都大于或等于其左右子孩子的值,这是大根堆;
或者每个结点的值都小于或等于其左右孩子结点的值,这是小根堆。
基本思想:
1. 先将已有的数组,形成一个大根堆,此时数组中最大的数必然是堆顶的元素,
2. 将堆中的最后一个元素和堆顶元素做交换,然后新的堆顶元素向下做调整,比较父节点是否比其子节点小,小的话,交换位置,向下调整。调整完毕之后,此时堆顶为除堆中最后一个元素之外的,最大的元素。需要一个辅助heapsize,每次调整完后减一
3. 重复上边操作,直到heapsize =0 ,数组变得有序。
代码如下:
#include <iostream>
using namespace std;
#include <vector>
#include<algorithm>
#include <math.h>
void print(vector<int>& arr) {
for (int i = 0; i < arr.size(); i++) {
cout << arr[i] << endl;
}
}
//1、 给一个数,将数插入,形成大根堆 (某个数处在index位置,往上继续移动)
void heapInsert(vector<int>& arr, int index) {
while (arr[index] > arr[(index - 1) / 2]) {
swap(arr[index], arr[(index - 1) / 2]);
index = (index - 1) / 2;
}
}
//2、 向下做调整 比较父节点是否比子节点小,小的话,往下走
void heapify(vector<int>& arr, int index, int heapSize) {
int left = 2 * index + 1;
while (left < heapSize) {
//比较左孩子和右孩子 ,哪个数比较大,将大的数的下标给largest
int largest = left + 1 < heapSize && arr[left+1] > arr[left] ? left+1 : left;
//int largest = left + 1 < heapSize && arr[left] >= arr[left+1] ? left : left+1; //就不对???
//比较父节点和最大孩子的大小 将大的给largest
largest = arr[largest] > arr[index] ? largest : index;
if (largest == index) {
break;
}
//将最大的数和父节点的数交换
swap(arr[largest], arr[index]);
index = largest;
left = index * 2 + 1;
}
}
//3、 进行堆排序
void heapSort(vector<int>& arr) {
//int heapSize = arr.size();
if (arr.size() < 2) return;
//该操作形成一个大根堆
for (int i = 0; i < arr.size(); i++) {
heapInsert(arr, i);
}
print1(arr);
//将最后一个数和第一个根节点做交换
int heapSize = arr.size();
heapSize--;
swap(arr[0], arr[heapSize]);
while (heapSize > 0) {
print1(arr);
heapify(arr, 0, heapSize);
heapSize--;
swap(arr[0], arr[heapSize]);
}
}
int main() {
vector<int> arr1 = {3,5,6,7,8,4,3,5,6,2,1,4};
heapSort(arr1);
print(arr1);
return 0;
}
三、计数排序
计数排序是一种非比较排序,常用于规模大,数字种类小的排序中,如考试成绩排名、人口年龄等等。思路很简单,但实现起来不容易,首先得定义两个数组,一个用于存放数字种类的个数,另一个用于存放排好序的数组。然后遍历整个数组,记录下数组中各数字的个数存放于第一个数组中,比如1出现一次,就存放于temp[arr[1]]中,然后再将这些出现的个数一次存放在新的数组中,从而达到排好序。
代码如下:
#include <iostream>
using namespace std;
#include <vector>
void countsort(vector<int>& arr) {
int n = arr.size();
vector<int> temp(1024), result(1024);
for (int i = 0; i < n; i++) {
temp[arr[i]]++;
}
for (int i = 0; i < n; i++) {
temp[i + 1] += temp[i];
}
for (int i = n - 1; i >= 0; i--) {
result[--temp[arr[i]]] = arr[i];
}
for (int i = 0; i < n; i++)//打印数组
{
cout << result[i] << " ";
}
}
int main(){
vector<int> arr = {3,7,1,5,2,9,3,8,4};
countsort(arr);
return 0;
}
四、基数排序
基数排序和计数排序原理差不多,但是适用范围更大一些。
#include <iostream>
using namespace std;
#include <vector>
#include <math.h>
void print(vector<int>& arr) {
for (int i = 0; i < arr.size(); i++) {
cout << arr[i] << endl;
}
}
int getDigit(int x, int d) {
int res = (x / (int)pow(10, d - 1)) % 10;
return res;
}
int maxbits(vector<int>& arr) {
int max1 = INT_MIN;
for (int i = 0; i < arr.size(); i++) {
max1 = max(max1, arr[i]);
}
int res = 0;
while (max1 != 0) {
res++;
max1 /= 10;
}
return res;
}
//digit 输入参数,事先应该确定数组中最大的数为多少位
void radixSort(vector<int>& arr, int L, int R, int digit) {
const int radix = 10;
int i = 0;
int j = 0;
vector<int> bucket;
//int m = R - L + 1;
bucket.resize(R - L + 1);
for (int d = 1; d <= digit; d++){
vector<int> count;
count.resize(radix);
for (i = L; i <= R; i++) {
j = getDigit(arr[i], d);
count[j]++;
}
for (i = 1; i < radix; i++ ){
count[i] = count[i] + count[i - 1];
}
for (i = R; i >= L; i--) {
j = getDigit(arr[i], d);
bucket[count[j] - 1] = arr[i];
count[j]--;
}
for (i = L, j = 0; i <= R; i++, j++) {
arr[i] = bucket[j];
}
}
}
int main(){
vector<int> arr = { 9, 5, 8, 2, 10, 3, 6, 18 ,4};
int m = maxbits(arr);
radixSort(arr, 0, arr.size() - 1,m);
print(arr);
return 0;
}
五、桶排序
桶排序的原理: 假设输入数据服从均匀分布,将数据分到有限数量的桶里,然后对每个桶分别排序(每个桶里数据排序可以选用上边的九种排序方法的任意一种),最后把全部桶的数据合并。
代码如下:对没有0元素的数组排序;且每个桶中元素的数量不超过5;
//假设每个桶中元素的数量不超过5;
void bucketsort(vector<int>& arr) {
int n = arr.size();
vector<vector<int>> bucket(5,vector<int>(5,0));
cout << "bucket二维数组初始化后为:" << endl;
for (int i = 0; i < bucket.size(); i++) {
for (int j = 0; j < bucket[0].size(); j++) {
cout << bucket[i][j] << " ";
}
cout << endl;
}
vector<int> bucketsize(5);//每个桶的计数器
for (int i = 0; i < n; i++) {
int m = arr[i] / 10;
bucket[m][bucketsize[m]++] = arr[i];
}
for (int i = 0; i < 5; i++) {
bubblesort1(bucket[i]);
}
cout << "排序完成之后各个桶的数据:" << endl;
for (int i = 0; i < bucket.size(); i++) {
for (int j = 0; j < bucket[0].size(); j++) {
cout << bucket[i][j] << " ";
}
cout << endl;
}
int k = 0;
cout << "排序后的arr数组变为:" << endl;
for (int i = 0; i < bucket.size(); i++) {
for (int j = 0; j < bucketsize[0].size(); j++) {
if (bucket[i][j] != 0) {
arr[k++] = bucket[i][j];
}
}
}
}
int main() {
vector<int> arr = {19,25,38,2,10,18,4};
bucketsort(arr);
print(arr);
return 0;
}
运行结果如下图: