题目:
用随机函数生成16个2位正整数(10~99),实现插入排序、选择排序、冒泡排序、双向冒泡、快速排序、二路归并排序等多种排序算法,输出排序中间过程、统计关键字的比较次数和记录的移动次数。
思路:
(1)插入排序:
- 从第一个元素开始,该元素可以认为已经被排序
- 取出下一个元素,在已经排序的元素序列中从后向前扫描
- 如果该元素(已排序)小于新元素,将新元素插入该元素下一位置
- 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置,将新元素插入到该位置后
- 若无,则将新元素插入最左侧
- 重复步骤2~5
(2)选择排序:从头至尾扫描序列,找出最小的一个元素,和第一个元素交换,接着从剩下的元素中继续这种选择和交换方式,最终得到一个有序序列。
(3)冒泡排序:让数组当中相邻的两个数进行比较,数组当中比较小的数值向下沉,数值比较大的向上浮!外层for循环控制循环次数,内层for循环控制相邻的两个元素进行比较。
(4)双向冒泡排序: - 比较相邻两个元素的大小。如果前一个元素比后一个元素大,则两元素位置交换
- 对数组中所有元素的组合进行第1步的比较
- 奇数趟时从左向右进行比较和交换
- 偶数趟时从右向左进行比较和交换
- 当从左端开始遍历的指针与从右端开始遍历的指针相遇时,排序结束
(5)快速排序:
1.先从数列中取出一个数作为基准数。
2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
3.再对左右区间重复第二步,直到各区间只有一个数。
(6)二路归并排序:归并排序是通过“归并”操作完成排序的,将两个或者多个有序子表归并成一个子表。归并排序是“分治法”的一个非常典型的应用,同事它也是递归算法的一个好的实例。它将问题分成一些小的问题然后递归求解,而治就是把分阶段的答案拼起来。
#include "pch.h"
#include <iostream>
#include<ctime>
#include<vector>
using namespace std;
void InsertSort(vector<int>num);//插入排序
void SelectSort(vector<int> num);//选择排序
void BubbleSort(vector<int> num);//冒泡排序
void ShakeSort(vector<int> num);//双向冒泡
void QuickSort(vector<int>&num, int low, int high, int &compare, int &swap);//快速排序
void MSort(vector<int>&num, int low, int high, int &compare, int &swap);
void Merge(vector<int> &num, int low, int mid, int high, int &compare, int &swap);
int main()
{
srand(unsigned int(time(0)));
vector<int> num(16);
cout << "初始数据如下:\n";
for (int i = 0; i < 16; i++)
{
num[i] = rand() % 89 + 10;
cout << num[i] << " ";
}
cout << endl;
cout << "插入排序中间过程如下:\n";
InsertSort(num);
cout << "选择排序中间过程如下:\n";
SelectSort(num);
cout << "冒泡排序中间过程如下:\n";
BubbleSort(num);
cout << "双向冒泡排序中间过程如下:\n";
ShakeSort(num);
cout << "快速排序中间过程如下:\n";
int compare = 0;
int swap = 0;
QuickSort(num, 0, num.size() - 1, compare, swap);
cout << "关键字比较次数:" << compare << '\t' << "移动次数:" << swap << endl;
cout << "初始数据如下:\n";
for (int i = 0; i < 16; i++)
{
num[i] = rand() % 89 + 10;
cout << num[i] << " ";
}
cout << endl;
compare = 0;
swap = 0;
cout << "归并排序中间过程如下:\n";
MSort(num, 0, num.size() - 1, compare, swap);
cout << "关键字比较次数:" << compare << '\t' << "移动次数:" << swap << endl;
}
void InsertSort(vector<int> num)//插入排序
{
int compare = 0;
int swap = 0;
for (int i = 1; i < 16; i++)
{//从第二个数开始寻找插入
int m = i;//当前实际位置
for (int j = i - 1; j >= 0; j--)
{//与前面的数比较
compare++;//比较次数增加
if (num[m] < num[j])//如果比前面数小
{
int tmp = num[m];
num[m] = num[j];
num[j] = tmp;//交换两数
swap++;//交换次数增加
for (int k = 0; k < 16; k++)
{//输出所有的数
cout << num[k] << " ";
}
cout << endl;
m--;//当前位置往前走
}
else break;
}
}
cout << "关键字比较次数:" << compare << '\t' << "移动次数:" << swap << endl;
}
void SelectSort(vector<int> num)
{
int compare=0;
int swap=0;
for (int i = 0; i < num.size(); i++)
{//查找最小数
int flag = i;//作为当前最小值下标
for (int j = i+1; j < num.size(); j++)
{//找到最小值
compare++;
if (num[j] < num[flag])
{
flag = j;
}
}
if (flag != i)
{//如果最小值不是当前值
swap++;
int tmp = num[i];
num[i] = num[flag];
num[flag] = tmp;//交换两数
for (int k = 0; k < 16; k++)
{//输出中间过程
cout << num[k] << " ";
}
cout << endl;
}
}
cout << "关键字比较次数:" << compare << '\t' << "移动次数:" << swap << endl;
}
void BubbleSort(vector<int> num)//冒泡排序
{
int compare = 0;//比较次数
int swap = 0;//交换次数
int flag = 1;//判断是否交换监视哨
for (int i = 0; i < num.size()&&flag; i++)
{//在有交换时才循环
flag = 0;
for (int j = 0; j < num.size()-i-1; j++)
{
compare++;//比较次数增加
if (num[j] > num[j + 1])
{//前大于后
flag = 1;//表示有交换
int tmp = num[j];
num[j] = num[j+1];
num[j+1] = tmp;//交换两数
swap++;
for (int k = 0; k < 16; k++)
{//输出中间过程
cout << num[k] << " ";
}
cout << endl;
}
}
}
cout << "关键字比较次数:" << compare << '\t' << "移动次数:" << swap << endl;
}
void ShakeSort(vector<int> num)//双向冒泡
{
int compare=0;
int swap = 0;
int pre = 0;//记录前面已排序的位置
int back = num.size() - 1;//记录前面未排序的位置
while (pre<back)
{//全部排序完毕后退出
for (int i = pre+1; i <= back; i++)
{//从前往后冒泡,找未排序最小值
compare++;
if (num[i] < num[pre])
{
swap++;
int tmp = num[i];
num[i] = num[pre];
num[pre] = tmp;
for (int k = 0; k < 16; k++)
{//输出中间过程
cout << num[k] << " ";
}
cout << endl;
}
}
pre++;
if (pre < back)
{//从后往前冒泡,找未排序最大值
for (int i = back-1; i >= pre; i--)
{
compare++;
if (num[i] > num[back])
{
swap++;
int tmp = num[i];
num[i] = num[back];
num[back] = tmp;
for (int k = 0; k < 16; k++)
{//输出中间过程
cout << num[k] << " ";
}
cout << endl;
}
}
back--;
}
}
cout << "关键字比较次数:" << compare << '\t' << "移动次数:" << swap << endl;
}
void QuickSort(vector<int>&num, int low, int high, int &compare, int &swap)//快速排序
{
if (low >= high) return;//若左大于等于右,说明low到high字段已排序完毕
int i = low;
int j = high;
int pivotkey = num[low];
while (i < j)
{
while (num[j] >= pivotkey && i < j)//从后找比标志数小的数
{
j--;
compare++;
}
if (i < j)//后面的数若比标志数小,移动到前面
{
swap++;
compare++;
num[i] = num[j];
for (int k = 0; k < 16; k++)
{//输出中间过程
cout << num[k] << " ";
}
cout << endl;
}
while (num[i] <= pivotkey && i < j)//从前找比标志数大的数
{
i++;
compare++;
}
if (i < j)//前面的数若比标志数小,移动到后面
{
compare++;
swap++;
num[j] = num[i];
for (int k = 0; k < 16; k++)
{//输出中间过程
cout << num[k] << " ";
}
cout << endl;
}
}
if (num[i] != pivotkey)
{
num[i] = pivotkey;//将中间重复的数置为标志数
swap++;
for (int k = 0; k < 16; k++)
{//输出中间过程
cout << num[k] << " ";
}
cout << endl;
}
QuickSort(num,low, i - 1,compare,swap);//继续处理左边的,这里是一个递归的过程
QuickSort(num,i + 1, high,compare,swap);//继续处理右边的 ,这里是一个递归的过程
}
void Merge(vector<int> &num, int low, int mid, int high, int &compare, int &swap)
{
int i = low;
int j = mid + 1;
int k = 0;
vector<int> tmp(high - low + 1);//临时存放数组
while (i <= mid && j <= high)
{//左右两部分进行比较,从小到大顺序放入临时数组
compare++;
if (num[i] <= num[j])
{
swap++;
tmp[k++] = num[i++];
for (int m = 0; m < k; m++)
{
cout << tmp[m] << " ";
}
cout << endl;
}
else
{
swap++;
tmp[k++] = num[j++];
for (int m = 0; m < k; m++)
{
cout << tmp[m] << " ";
}
cout << endl;
}
}
while (i <= mid)
{//左数组有剩余,全部放入临时数组
swap++;
tmp[k++] = num[i++];
for (int m = 0; m < k; m++)
{
cout << tmp[m] << " ";
}
cout << endl;
}
while (j <= high)
{//右数组有剩余,全部放入临时数组
swap++;
tmp[k++] = num[j++];
for (int m = 0; m < k; m++)
{
cout << tmp[m] << " ";
}
cout << endl;
}
for (i = low, k = 0; i <= high; i++, k++)
{//将临时数组数据存入排序数组中
num[i] = tmp[k];
}
}
void MSort(vector<int>&num, int low, int high,int &compare,int &swap)
{//分治过程
if (low < high)
{
int mid = (low + high) / 2;//分割左右两部分
MSort(num, low, mid,compare,swap);//对左部分继续分割
MSort(num, mid + 1, high,compare,swap);//对右部分继续分割
Merge(num, low, mid, high,compare,swap);//进行归并排序
}
}