C++ 内排序算法

本文提供了C++实现的多种内排序算法,包括冒泡排序、快速排序、希尔排序、插入排序(直接插入和折半插入)、选择排序和堆排序。同时,通过QueryPerformanceCounter和QueryPerformanceFrequency函数计算了每种排序算法的执行时间,以评估其效率。
摘要由CSDN通过智能技术生成

内排序算法所涉及的结构体类型

typedef int KeyType;
typedef char InfoType;
typedef struct
{
	KeyType key;
	//InfoType otherinfo;
}RecType;

时间处理--计算排序所花费的时间

    LARGE_INTEGER nFreq;
	LARGE_INTEGER nBeginTime;
	LARGE_INTEGER nEndTime;
	double T;
	srand(time(0));
	cout.setf(ios::fixed);
	
	Random(R, 80);
	cout << "\n冒泡排序" << endl;
	QueryPerformanceFrequency(&nFreq);
	QueryPerformanceCounter(&nBeginTime);

	BubbleSort(R, 80);
	QueryPerformanceCounter(&nEndTime);
	T = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) * 1000000000 / (double)(nFreq.QuadPart);
	cout << "时间:" << setprecision(2) << setiosflags(ios::fixed) << (double)T << endl;
	Disp(R, 80);
	cout << "\n\n";

随机数生成

void Random(RecType *R,int n)
{
	cout << "排序前" << endl;
	for (int i = 0; i < n; i++)
	{
		R[i].key = rand() % 10000;
		cout<<R[i].key<<" ";
	}
}

一、插入排序

1.简单插入排序

void InsertSort(RecType R[], int n)
{
	int i, j;
	RecType tmp;
	for (i = 1; i < n; i++)//比较n-1次
	{
		if (R[i].key < R[i - 1].key)//反序时
		{
			tmp = R[i];
			j = i - 1;
			do					//寻找R[i]的插入位置
			{
				R[j + 1] = R[j];//将关键字大于R[i].key的记录后移
				j--;
			} while (j >= 0 && R[j].key > tmp.key);//
			R[j + 1] = tmp;	//在j+1处插入R[i].
		}
	}
}

2.折半插入排序

因为每次排序时,前面是有序区(局部有序),可以采用折半查找的思想,找到相应的位置,再进行元素的插入。

void BinInsertSort(RecType R[],int n)
{
	int i, j, low, high, mid;
	RecType tmp;
	for (i = 1; i < n; i++)//比较n-1次
	{
		if (R[i].key < R[i - 1].key)		//反序时
		{
			low = 0;
			high = i-1;
			tmp = R[i];						//将R[i]保存到tmp中
			while (low <= high)				//寻找查找位置
			{
				mid = (high + low) / 2;		//取中间位置
				if (tmp.key > R[mid].key)
				{
					low = mid + 1;			//插入点在右半区
				}
				else
				{
					high = mid - 1;			//插入点在左半区
				}
			}								//找位置high+1
			for (j = i - 1; j >= high + 1; j--)
			{
				R[j + 1] = R[j];
			}
			R[high + 1] = tmp;				//插入tmp
		}
	}
}

3.希尔排序

void ShellSort(RecType R[],int n)//希尔排序算法
{
	int i, j, d;
	RecType tmp;
	d = n / 2;			//增量置初值
	while (d > 0)
	{
		for (i = d; i < n; i++)	//对所有组采用直接插入排序
		{
			tmp = R[i];			//对相隔位置为d的一组进行直接插入排序
			j = i - d;
			while (j>=0 && tmp.key>R[j].key)
			{
				R[j + 1] = R[j];
				j = j - d;
			}
			R[j + d] = tmp;
		}
		d /= 2;			//减小增量
	}
}

二、交换排序

1.冒泡排序

void BubbleSort(RecType R[], int n)
{
	for (int i = 0; i < n; i++)
	{
		for (int j = n-1; j >0; j--)	//将R[i]元素归位
		{
			if (R[j].key > R[j-1].key) //相邻的两个元素反序时
			{
				RecType temp = R[j];	//将R[j]和R[j-1]进行交换
				R[j ] = R[j-1];
				R[j-1] = temp;
			}
		}
	}
}

2.快速排序

采用了递归的思想

注意递归的出口,每次递归的参数

a. Partition(RecType R[],int s,int t);获取已排序完成的元素的位置--此处是全局有序(归位)。

b.QuickSort(RecType R[],int s,int t);反复递归,直到只剩下一个元素,即有序。

int Partition(RecType R[],int s,int t)
{
	int i = s, j = t;
	RecType base = R[i];
	while (i < j)
	{
		while (j > i && R[j].key >= base.key)
		{
			j--;
		}
		if (R[j].key < base.key)
		{
			R[i] = R[j];
			i++;
		}
		while (j > i && R[i].key <= base.key)
		{
			i++;
		}
		if (R[i].key > base.key)
		{
			R[j] = R[i];
			j--;
		}
	}
	R[i] = base;
	return i;
}
void QuickSort(RecType R[],int s,int t)
{
	int i;
	if (s < t)
	{
		i = Partition(R, s, t);
		QuickSort(R, s, i - 1);
		QuickSort(R, i + 1, t);
	}
}

三、选择排序

1.选择排序

void SortAlgorithm(RecType R[], int n)
{
	for (int i = 0; i < n; i++)
	{
		int minindex = i;
		for (int j = i + 1; j < n; j++)
		{
			if (R[minindex].key > R[j].key)
			{
				minindex = j;
			}
		}
		RecType temp = R[i];
		R[i] = R[minindex];
		R[minindex] = temp;
	}
}

2.堆排序

此排序涉及大小根堆等相关概念。

排序开始,先初始化一个大根堆

接着不断地交换根节点的元素,此过程中,会不断通过sift函数进行根堆的调整。(复杂)

//堆排序 -- 树形选择排序方法
void sift(RecType R[], int low, int high)
{
	int i = low, j = 2 * i;	//R[j]是R[i]的左孩子
	RecType tmp = R[i];
	while (j <= high)
	{
		if (j < high && R[j].key < R[j + 1].key)//若右孩子较大,则j指向右孩子
		{
			j++;
		}
		if (tmp.key < R[j].key)	//若根结点小于最大孩子的关键字
		{
			R[i] = R[j];  //将R[j]调整到双亲结点位置上
			i = j;			//修改i和j值,以便继续向下筛选
			j = 2 * i;
		}
		else break;			//若根节点大于或等于最大孩子的关键字,筛选结束
	}
	R[i] = tmp;		//被筛选节点放到最终位置上
}
void HeapSort(RecType R[],int n)
{
	int i;
	for (i = n / 2; i >= 1; i--)
	{
		sift(R, i, n);		//循环建立初始堆,调用sift算法
	}
	for (i = n; i >= 2; i--)	//进行n-1趟完成堆排序,每一趟堆的元素个数-1
	{		
		swap(R[1], R[i]);		//将最后一个元素与根R[1]交换
		sift(R, 1, i - 1);		//将R[1…i-1]进行筛选,得到i-1个结点的堆
	}
}

四、完整代码实现

注意:代码中有两个Random,两个Disp(堆排序的缘故),目前只能做到这样,水平有限,希望获得宝贵的意见。

#include<iostream>
using namespace std;
#define MAXL 100
#include <ctime>
#include <windows.h>
#include <iomanip>
typedef int KeyType;
typedef char InfoType;
typedef struct
{
	KeyType key;
	//InfoType otherinfo;
}RecType;

//交换排序
//冒泡排序
void BubbleSort(RecType R[], int n)
{
	for (int i = 0; i < n; i++)
	{
		for (int j = n-1; j >0; j--)	//将R[i]元素归位
		{
			if (R[j].key > R[j-1].key) //相邻的两个元素反序时
			{
				RecType temp = R[j];	//将R[j]和R[j-1]进行交换
				R[j ] = R[j-1];
				R[j-1] = temp;
			}
		}
	}
}
//快速排序
int Partition(RecType R[],int s,int t)
{
	int i = s, j = t;
	RecType base = R[i];
	while (i < j)
	{
		while (j > i && R[j].key >= base.key)
		{
			j--;
		}
		if (R[j].key < base.key)
		{
			R[i] = R[j];
			i++;
		}
		while (j > i && R[i].key <= base.key)
		{
			i++;
		}
		if (R[i].key > base.key)
		{
			R[j] = R[i];
			j--;
		}
	}
	R[i] = base;
	return i;
}
void QuickSort(RecType R[],int s,int t)
{
	int i;
	if (s < t)
	{
		i = Partition(R, s, t);
		QuickSort(R, s, i - 1);
		QuickSort(R, i + 1, t);
	}
}
//选择排序
//简单选择排序
void SortAlgorithm(RecType R[], int n)
{
	for (int i = 0; i < n; i++)
	{
		int minindex = i;
		for (int j = i + 1; j < n; j++)
		{
			if (R[minindex].key > R[j].key)
			{
				minindex = j;
			}
		}
		RecType temp = R[i];
		R[i] = R[minindex];
		R[minindex] = temp;
	}
}
//堆排序 -- 树形选择排序方法
void sift(RecType R[], int low, int high)
{
	int i = low, j = 2 * i;	//R[j]是R[i]的左孩子
	RecType tmp = R[i];
	while (j <= high)
	{
		if (j < high && R[j].key < R[j + 1].key)//若右孩子较大,则j指向右孩子
		{
			j++;
		}
		if (tmp.key < R[j].key)	//若根结点小于最大孩子的关键字
		{
			R[i] = R[j];  //将R[j]调整到双亲结点位置上
			i = j;			//修改i和j值,以便继续向下筛选
			j = 2 * i;
		}
		else break;			//若根节点大于或等于最大孩子的关键字,筛选结束
	}
	R[i] = tmp;		//被筛选节点放到最终位置上
}
void HeapSort(RecType R[],int n)
{
	int i;
	for (i = n / 2; i >= 1; i--)
	{
		sift(R, i, n);		//循环建立初始堆,调用sift算法
	}
	for (i = n; i >= 2; i--)	//进行n-1趟完成堆排序,每一趟堆的元素个数-1
	{		
		swap(R[1], R[i]);		//将最后一个元素与根R[1]交换
		sift(R, 1, i - 1);		//将R[1…i-1]进行筛选,得到i-1个结点的堆
	}
}
//插入排序
//直接插入排序
void InsertSort(RecType R[], int n)
{
	int i, j;
	RecType tmp;
	for (i = 1; i < n; i++)//比较n-1次
	{
		if (R[i].key < R[i - 1].key)//反序时
		{
			tmp = R[i];
			j = i - 1;
			do					//寻找R[i]的插入位置
			{
				R[j + 1] = R[j];//将关键字大于R[i].key的记录后移
				j--;
			} while (j >= 0 && R[j].key > tmp.key);//
			R[j + 1] = tmp;	//在j+1处插入R[i].
		}
	}
}
//折半插入排序
void BinInsertSort(RecType R[],int n)
{
	int i, j, low, high, mid;
	RecType tmp;
	for (i = 1; i < n; i++)//比较n-1次
	{
		if (R[i].key < R[i - 1].key)		//反序时
		{
			low = 0;
			high = i-1;
			tmp = R[i];						//将R[i]保存到tmp中
			while (low <= high)				//寻找查找位置
			{
				mid = (high + low) / 2;		//取中间位置
				if (tmp.key > R[mid].key)
				{
					low = mid + 1;			//插入点在右半区
				}
				else
				{
					high = mid - 1;			//插入点在左半区
				}
			}								//找位置high+1
			for (j = i - 1; j >= high + 1; j--)
			{
				R[j + 1] = R[j];
			}
			R[high + 1] = tmp;				//插入tmp
		}
	}
}
//希尔排序
void ShellSort(RecType R[],int n)//希尔排序算法
{
	int i, j, d;
	RecType tmp;
	d = n / 2;			//增量置初值
	while (d > 0)
	{
		for (i = d; i < n; i++)	//对所有组采用直接插入排序
		{
			tmp = R[i];			//对相隔位置为d的一组进行直接插入排序
			j = i - d;
			while (j>=0 && tmp.key>R[j].key)
			{
				R[j + 1] = R[j];
				j = j - d;
			}
			R[j + d] = tmp;
		}
		d /= 2;			//减小增量
	}
}
//打印数据
void Disp(RecType* arr, int n)
{
	cout << "排序后" << endl;
	for (int i = 0; i < n; i++)
	{
		cout << arr[i].key<< " ";
	}
}
void Dispsift(RecType* arr, int n)
{
	cout << "排序后" << endl;
	for (int i = 1; i < n; i++)
	{
		cout << arr[i].key << " ";
	}
}
void Random(RecType *R,int n)
{
	cout << "排序前" << endl;
	for (int i = 0; i < n; i++)
	{
		R[i].key = rand() % 10000;
		cout<<R[i].key<<" ";
	}
}

void random0(RecType* R, int n)
{
	cout << "排序前" << endl;
	for (int i = 1; i < n; i++)
	{
		R[i].key = rand() % 10000;
		cout << R[i].key << " ";
	}
}
void Time(RecType R[], int n)
{
	LARGE_INTEGER nFreq;
	LARGE_INTEGER nBeginTime;
	LARGE_INTEGER nEndTime;
	double T;
	srand(time(0));
	cout.setf(ios::fixed);
	
	Random(R, 80);
	cout << "\n冒泡排序" << endl;
	QueryPerformanceFrequency(&nFreq);
	QueryPerformanceCounter(&nBeginTime);

	BubbleSort(R, 80);
	QueryPerformanceCounter(&nEndTime);
	T = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) * 1000000000 / (double)(nFreq.QuadPart);
	cout << "时间:" << setprecision(2) << setiosflags(ios::fixed) << (double)T << endl;
	Disp(R, 80);
	cout << "\n\n";

	Random(R, 80);
	cout << "\n快速排序" << endl;
	QueryPerformanceFrequency(&nFreq);
	QueryPerformanceCounter(&nBeginTime);
	
	QuickSort(R, 0, 79);

	QueryPerformanceCounter(&nEndTime);
	T = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) * 1000000000 / (double)(nFreq.QuadPart);
	cout << "时间:" << setprecision(2) << setiosflags(ios::fixed) << (double)T << endl;
	Disp(R, 80);
	cout << "\n\n";

	Random(R, 80);
	cout << "\n希尔排序" << endl;
	QueryPerformanceFrequency(&nFreq);
	QueryPerformanceCounter(&nBeginTime);
	
	ShellSort(R, 79);
	QueryPerformanceCounter(&nEndTime);
	T = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) * 1000000000 / (double)(nFreq.QuadPart);
	cout << "时间:" << setprecision(2) << setiosflags(ios::fixed) << (double)T << endl;
	Disp(R, 80);
	cout << "\n\n";

	Random(R, 80);
	cout << "\n折半插入排序" << endl;
	QueryPerformanceFrequency(&nFreq);
	QueryPerformanceCounter(&nBeginTime);
	
	BinInsertSort(R, 80);
	QueryPerformanceCounter(&nEndTime);
	T = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) * 1000000000 / (double)(nFreq.QuadPart);
	cout << "时间:" << setprecision(2) << setiosflags(ios::fixed) << (double)T << endl;
	Disp(R, 80);
	cout << "\n\n";

	Random(R, 80);
	cout << "\n简单插入排序" << endl;
	QueryPerformanceFrequency(&nFreq);
	QueryPerformanceCounter(&nBeginTime);
	
	InsertSort(R, 80);
	QueryPerformanceCounter(&nEndTime);
	T = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) * 1000000000 / (double)(nFreq.QuadPart);
	cout <<"时间:" << setprecision(2) << setiosflags(ios::fixed) << (double)T << endl;
	Disp(R, 80);
	cout << "\n\n";

	Random(R, 80);
	cout << "\n选择排序" << endl;
	QueryPerformanceFrequency(&nFreq);
	QueryPerformanceCounter(&nBeginTime);

	SortAlgorithm(R, 80);
	QueryPerformanceCounter(&nEndTime);
	T = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) * 1000000000 / (double)(nFreq.QuadPart);
	cout << "时间:" << setprecision(2) << setiosflags(ios::fixed) << (double)T << endl;
	Disp(R, 80);
	cout << "\n\n";

	RecType R0[81];
	random0(R0,81);
	cout << "\n堆排序" << endl;
	QueryPerformanceFrequency(&nFreq);
	QueryPerformanceCounter(&nBeginTime);

	HeapSort(R0, 80);
	QueryPerformanceCounter(&nEndTime);
	T = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) * 1000000000 / (double)(nFreq.QuadPart);
	cout << "时间:" << setprecision(2) << setiosflags(ios::fixed) << (double)T << endl;
	Dispsift(R0, 81);
	cout << "\n";
}
int main()
{
	RecType R[80];
	
	Time(R, 80);
	return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值