数据结构:各种排序算法的实现

题目:

用随机函数生成16个2位正整数(10~99),实现插入排序、选择排序、冒泡排序、双向冒泡、快速排序、二路归并排序等多种排序算法,输出排序中间过程、统计关键字的比较次数和记录的移动次数。

思路:

(1)插入排序:

  1. 从第一个元素开始,该元素可以认为已经被排序
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
  3. 如果该元素(已排序)小于新元素,将新元素插入该元素下一位置
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置,将新元素插入到该位置后
  5. 若无,则将新元素插入最左侧
  6. 重复步骤2~5
    (2)选择排序:从头至尾扫描序列,找出最小的一个元素,和第一个元素交换,接着从剩下的元素中继续这种选择和交换方式,最终得到一个有序序列。
    (3)冒泡排序:让数组当中相邻的两个数进行比较,数组当中比较小的数值向下沉,数值比较大的向上浮!外层for循环控制循环次数,内层for循环控制相邻的两个元素进行比较。
    (4)双向冒泡排序:
  7. 比较相邻两个元素的大小。如果前一个元素比后一个元素大,则两元素位置交换
  8. 对数组中所有元素的组合进行第1步的比较
  9. 奇数趟时从左向右进行比较和交换
  10. 偶数趟时从右向左进行比较和交换
  11. 当从左端开始遍历的指针与从右端开始遍历的指针相遇时,排序结束
    (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);//进行归并排序
	}
}
发布了330 篇原创文章 · 获赞 13 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43981315/article/details/103915727