承接上一篇的常用排序算法的c++语言实现
**4.希尔排序:**把记录按下表的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止
**5.快速排序:**通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
**6.归并排序:**一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
**7.堆排序:**利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
#include<iostream>
using namespace std;
//遍历数组
void traverse(int* arr, int len) {
for (int i = 0; i < len; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
//交换函数
void swap(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
//冒泡排序
void Bubble_Sort(int* a, int len) {
for (int i = 0; i < len - 1; i++) {
int flag = 0;
for (int j = 0; j < len - 1 - i; j++) {
if (a[j] > a[j+1]) {
swap(a[j], a[j+1]);
flag = 1;
}
}
if (flag == 0)break;
}
}
//选择排序,不稳定
void Selection_Sort(int* arr, int len) {
for (int i = 0; i < len - 1; i++) {
int index = i;
for (int j = 1 + i; j < len; j++) {
if (arr[index] > arr[j]) {
index = j;
}
}
swap(arr[index], arr[i]);
}
}
//插入排序
void Insertion_Sort(int* arr, int len) {
for (int i = 0; i < len-1 ; i++) {
for (int j = i; j >=0; j--) {
if (arr[j] > arr[j + 1]) {
swap(arr[j], arr[j + 1]);
}
else break;
}
}
}
//希尔排序:更高效的插入排序,不稳定
void Shell_Sort(int* arr, int len) {
for (int gap = len / 2; gap > 0; gap /= 2) {
for (int i = gap; i < len; i++) {
for (int j = i - gap; j >= 0; j -= gap) {
if (arr[j] > arr[j + gap]) {
swap(arr[j], arr[j + gap]);
}
else break;
}
}
}
}
//快速排序,不稳定
void Quick_Sort(int* arr, int left, int right) {
int l = left;// 左下标
int r = right;// 右下标
int pivot = arr[(left + right) / 2];// 找到中间的值
// 将比pivot小的值放在其左边,比pivot大的值放在其右边
while (l < r) {
// 在pivot左边寻找,直至找到大于等于pivot的值才退出
while (arr[l] <pivot) {
l += 1;// 将l右移一位
}
// 在pivot右边寻找,直至找到小于等于pivot的值才退出
while (arr[r] > pivot) {
r -= 1;// 将r左移一位
}
if (l >= r) {
// 左右下标重合,寻找完毕,退出循环
break;
}
// 交换元素
swap(arr[r], arr[l]);
//倘若发现值相等的情况,则没有比较的必要,直接移动下标即可
// 如果交换完后,发现arr[l]==pivot,此时应将r左移一位
if (arr[l] == pivot) {
r -= 1;
}
// 如果交换完后,发现arr[r]==pivot,此时应将l右移一位
if (arr[r] == pivot) {
l += 1;
}
}
// 如果l==r,要把这两个下标错开,否则会出现无限递归,导致栈溢出的情况
if (l == r) {
l += 1;
r -= 1;
}
// 向左递归
if (left < r) {
Quick_Sort(arr, left, r);
}
// 向右递归
if (right > l) {
Quick_Sort(arr, l, right);
}
}
//归并排序
void merge(int* arr, int left, int right, int mid, int* temp) {
int i = left; // 初始化i,左边有序序列的初始索引
int j = mid + 1;// 初始化j,右边有序序列的初始索引(右边有序序列的初始位置即为中间位置的后一个位置)
int t = 0;// 指向temp数组的当前索引,初始为0
// 先把左右两边的数据(已经有序)按规则填充到temp数组
// 直到左右两边的有序序列,有一边处理完成为止
while (i <= mid && j <= right) {
// 如果左边有序序列的当前元素小于或等于右边有序序列的当前元素,就将左边的元素填充到temp数组中
if (arr[i] <= arr[j]) {
temp[t] = arr[i];
t++;// 索引后移
i++;// i后移
}
else {
// 反之,将右边有序序列的当前元素填充到temp数组中
temp[t] = arr[j];
t++;// 索引后移
j++;// j后移
}
}
// 把有剩余数据的一边的元素填充到temp中
while (i <= mid) {
// 此时说明左边序列还有剩余元素
// 全部填充到temp数组
temp[t] = arr[i];
t++;
i++;
}
while (j <= right) {
// 此时说明左边序列还有剩余元素
// 全部填充到temp数组
temp[t] = arr[j];
t++;
j++;
}
// 将temp数组的元素复制到原数组
t = 0;
int tempLeft = left;
while (tempLeft <= right) {
arr[tempLeft] = temp[t];
t++;
tempLeft++;
}
}
void Merge_Sort(int*arr, int left, int right, int* temp) {
// 分解
if (left < right) {
int mid = (left + right) / 2;// 中间索引
// 向左递归进行分解
Merge_Sort(arr, left, mid, temp);
// 向右递归进行分解
Merge_Sort(arr, mid + 1, right, temp);// mid + 1,中间位置的后一个位置才是右边序列的开始位置
// 每分解一轮便合并一轮
merge(arr, left, right, mid, temp);
}
}
//堆排序
// 调整使之成为最大堆
void adjustHeap(int*arr, int i,int len) {
int maxIndex = i;
//如果有左子树,且左子树大于父节点,则将最大指针指向左子树
if (i * 2 < len && arr[i * 2] > arr[maxIndex])
maxIndex = i * 2;
//如果有右子树,且右子树大于父节点,则将最大指针指向右子树
if (i * 2 + 1 < len && arr[i * 2 + 1] > arr[maxIndex])
maxIndex = i * 2 + 1;
//如果父节点不是最大值,则将父节点与最大值交换,并且递归调整与父节点交换的位置。
if (maxIndex != i) {
swap(arr[maxIndex],arr[i]);
adjustHeap(arr, maxIndex,len);
}
}
//构建最大堆函数
void Build_MaxHeap(int* arr, int len) {
//从最后一个非叶子节点开始向上构造最大堆
for (int i = (len / 2 - 1); i >= 0; i--) {
adjustHeap(arr, i, len);
}
}
void Heap_Sort(int* arr, int len) {
//1.构建最大堆
Build_MaxHeap(arr, len);
//2.循环将堆首位(最大值)与末位交换,然后在重新调整最大堆
while (len > 0) {
swap(arr[0], arr[len - 1]);
len--;
adjustHeap(arr, 0,len);
}
}
int main() {
int arr[10] = { 1,3,5,7,9,2,4,6,8,0 };
int len = sizeof(arr) / sizeof(arr[0]);
traverse(arr, len);
Bubble_Sort(arr, len);
Selection_Sort(arr, len);
Insertion_Sort(arr, len);
Shell_Sort(arr,len);
int left = 0;
int right = 9;
Quick_Sort(arr, left, right);
int* temp = new int[10];
Merge_Sort(arr, left, right,temp);
Heap_Sort(arr, len);
traverse(arr, len);
system("pause");
return 0;
}