七种排序算法C++版

 

 


一、交换排序之~~冒泡排序

1.一种简单的交换排序

将序列中的数据,从前向后遍历循环,作为被比较数;(外循环)

将剩余数据作为比较数,从前向后,依次进行比较;(内循环)

把较小数据的交换到靠前位置;

每一次循环比较,都能将剩余数据中最小的数据交换到最前边,

思想简单,效率最低。

2.冒泡排序

将序列中的数据,从前向后遍历,控制循环;(外循环)

将序列中的数据,从后向前遍历,将相邻两个数据进行比较,小数交换到靠前位置;(内循环)

这样的排序,每次循环比较,不仅能将最小的数据交换到最前边,还能将其他较小数据的位置向前挪;

效率有所提升。                                                                                                                                                          

3.冒泡排序的优化版本

设置状态变量Flag

将序列中的数据,从前向后遍历,控制循环;每次循环开始,将Flag置为False;

将序列中的数据,从后向前遍历,相邻两个数据进行比较,小数交换到靠前位置,且发生交换,则Flag置为True;

当某次外循环,数据已经有序,则遍历过程中不发生数据交换,Flag一直处于False状态,直接跳出外循环,认为排序结束。

这样的排序,若序列已经有序,则无需继续进行排序;

效率进一步提升。

二、交换排序之~~快速排序

从序列中选择关键字(如第一个数据)

一趟排序:按照关键词,将输入序列分为两部分,左部分比关键字小,右部分比关键字大;

分别对得到的这两部分再次进行排序,递归完成排序;

四种交换排序代码如下:

//三种冒泡排序算法比较
// 快速排序
#include <iostream>
#include <vector>
#include <ctime>

using namespace std;

void BubbleSortLow(vector <int> chaosData, int num);
void BubbleSortMid(vector <int> chaosData, int num);
void BubbleSortHight(vector <int> chaosData, int num);
int QuickSortPar(vector <int> &chaosData, int low, int high);
void QuickSort(vector <int> &chaosData, int low, int high);


int SwapNum(int &num1, int &num2);

int main()
{
	int num = 10;
	srand((unsigned)time(NULL));
	cout << "功能:将数据从大到小排序\n" << endl;
	vector <int> chaosData;
	for (int i = 0; i != num; ++i)
	{
		chaosData.push_back(rand() % 100); //产生0~100的整型数据
	}
	cout << "排序前数据为:" << endl;
	for (auto c : chaosData)
	{
		cout << c << " ";
	}

	cout << endl << "1.效率较低的一种冒泡排序:" << endl;
	clock_t clockLowB = clock();
	BubbleSortLow(chaosData, num);
	clock_t clockLowE = clock();
	cout << "第1种方法运行时间为:" << (double)(clockLowE - clockLowB) << "毫秒" << endl;
	
	cout << endl << "2.正宗的一种冒泡排序:" << endl;
	clock_t clockMidB = clock();
	BubbleSortMid(chaosData, num);
	clock_t clockMidE = clock();
	cout << "第2种方法运行时间为:" << (double)(clockMidE - clockMidB) << "毫秒" << endl;

	cout << endl << "3.优化后的一种冒泡排序:" << endl;
	clock_t clockHighB = clock();
	BubbleSortHight(chaosData, num);
	clock_t clockHighE = clock();
	cout << "第3种方法运行时间为:" << (double)(clockHighE - clockHighB) << "毫秒" << endl;


	vector <int> &chaosDataNew = chaosData;

	cout << endl << "4.快速排序:" << endl;
	clock_t clockQuickB = clock();
	QuickSort(chaosDataNew, 0, num - 1);
	clock_t clockQuickE = clock();
	cout << "第4种方法运行时间为:" << (double)(clockQuickE - clockQuickB) << "毫秒" << endl;
	

	cout << "排序后数据为:" << endl;
	for (auto c : chaosDataNew)
	{
		cout << c << " ";
	}

	system("pause");
	return 0;
}

// 0.交换两个整型数据
int SwapNum(int &num1, int &num2)
{
	int tempNum = 0;

	tempNum = num1;
	num1 = num2;
	num2 = tempNum;

	return 0;
}

// 1.效率较低的一种冒泡排序
void BubbleSortLow(vector <int> chaosData, int num)
{
	for (int i = 0; i != num-1; ++i)
	{
		for (int j = i + 1; j != num; ++j)
		{
			if (chaosData[i] > chaosData[j])
			{
				SwapNum(chaosData[i], chaosData[j]);
			}
		}
	}
	cout << "排序后数据为:" << endl;
	for (auto c : chaosData)
	{
		cout << c << " ";
	}

}

// 2.正宗的一种冒泡排序:
void BubbleSortMid(vector <int> chaosData, int num)
{
	for (int i = 0; i <= num - 1; ++i)
	{
		for (int j = num - 1; j >= i && j > 0; --j) // j>i
		{
			if (chaosData[j-1] > chaosData[j])
			{
				SwapNum(chaosData[j-1], chaosData[j]);
			}
		}
	}
	cout << "排序后数据为:" << endl;
	for (auto c : chaosData)
	{
		cout << c << " ";
	}
}

// 3.优化后的一种冒泡排序:
void BubbleSortHight(vector <int> chaosData, int num)
{
	int flag; // 为1则已经有序

	for (int i = 0; i <= num - 1; ++i) // 循环判断:i未至最大数值 且 此时无序;flag为1则跳出循环
	{
		flag = 1; //无序
		for (int j = num - 1; j >= i && j > 0; --j)
		{
			if (chaosData[j - 1] > chaosData[j])
			{
				SwapNum(chaosData[j - 1], chaosData[j]);
				flag = 0;
			}

		}

		if (flag == 1)
			break;
	}
	cout << "排序后数据为:" << endl;
	for (auto c : chaosData)
	{
		cout << c << " ";
	}
}

// 4.快速排序

void QuickSort(vector <int> &chaosData, int low, int high)
{
	int flag;
	if (low < high)
	{
		flag = QuickSortPar(chaosData, low, high);
		QuickSort(chaosData, low, flag - 1);
		QuickSort(chaosData, flag + 1, high);
	}

}

int QuickSortPar(vector <int> &chaosData, int low, int high)
{
	int keyNum = chaosData[low]; // 将序列中的第一个数字作为关键字
	//low为左侧标志,high为右侧标志;从左到右从小到大
	while (low < high)
	{
		while (low < high && chaosData[high] > keyNum)
		{
			--high;
		}
		SwapNum(chaosData[high], chaosData[low]);

		while (low < high && chaosData[low] < chaosData[high])
		{
			++low;
		}
		SwapNum(chaosData[high], chaosData[low]);
	}

	cout << "调用low=" << low << "    high=" << high << endl;
	return low; //low和high相等

}

三、选择排序之~~简单选择排序

将序列从前向后,依次循环遍历,首先认为第一个位置的数字是最小的,记最小数字的位置为min;(外循环)

将剩余数字和第一个位置数字比较,若发现更小的数字,则将min的值改为该位置;(内循环)

每次外循环,得到min位置,将min位置和外循环开始位置的数字互换,则最小的数字被选择到了序列首位;

依次进行外循环;

四、选择排序之~~堆排序

堆的定义:

每个结点的值 大于或等于 其左右孩子结点的值(大顶堆)

每个结点的值 小于或等于 其左右孩子结点的值(小顶堆)

结点 的左孩子结点为:2 * i + 1;右孩子结点为: 2 * i + 2

第一个非叶结点:len / 2 - 1

堆排序的思想:将无序数据构造为堆结构,将堆顶元素输出,再将剩余元素重新构造为堆,继续输出堆顶元素;

问题①:如何将无序数据构造为堆结构?.

从无序数据的第一个非叶结点开始,依次调整,直到调整至根节点;

针对某个结点的堆调整,设置标号minId,,初始化为该结点的位置;

将该结点及其左右孩子结点中 最小结点的位置 赋给 minId

minId仍然是该结点的位置,则继续调整下一个非叶结点。

否则,将该结点和最小数据结点互换位置,发并以新的minId位置作为非叶结点,重新进行堆调整;

问题②:如何将堆顶元素之外的元素重新调整为堆?

将调整好的堆结构根节点元素 与 最后位置的元素互换位置,并输出,此时得到了序列中的最小数据;

此时,最后位置的元素成为了新的根节点,通过新的根节点调整堆结构,得到新的堆,再次输出根节点,依次循环;

//选择排序
#include <iostream>
#include <ctime>
#include <Windows.h>

using namespace std;

void SelectionSort(int chaosData[], int len);
void HeapSort(int chaosData[], int len);
void adjust(int chaosData[], int len, int index);

int SwapNum(int &num1, int &num2);

int main()
{
	int chaosData[10];
	int len = 10;
	srand((unsigned)time(NULL));
	cout << "功能:对数据从大到小排序\n" << endl;
	for (int i = 0; i != len; ++i)
	{
		chaosData[i] = (rand() % 100); //产生0~100的整型数据
	}
	cout << "排序前数据为:" << endl;
	for (int i = 0; i < len; ++i)
	{
		cout << chaosData[i] << " ";
	}

// 	cout << endl << "\n1.选择排序:" << endl;
// 	clock_t clockLowB = clock();
// 	SelectionSort(chaosData, len);
// 	clock_t clockLowE = clock();
// 	cout << "\n第1种方法运行时间为:" << (double)(clockLowE - clockLowB)  << "毫秒" << endl;

	cout << endl << "\n2.堆排序:" << endl;
	clock_t clockMidB = clock();
	HeapSort(chaosData, len);
	clock_t clockMidE = clock();
	cout << "\n第1种方法运行时间为:" << (double)(clockMidE - clockMidB) << "毫秒" << endl;

	system("pause");
	return 0;
}

// 0.交换两个整型数据
int SwapNum(int &num1, int &num2)
{
	int tempNum = 0;

	tempNum = num1;
	num1 = num2;
	num2 = tempNum;

	return 0;
}

// 1.选择排序
void SelectionSort(int chaosData[], int len)
{
	int i, j;
	int min;
	for (i = 0; i <= len - 1; ++i)
	{
		min = i;
		for (j = i + 1;j < len; ++j)
		{
			if (chaosData[min] > chaosData[j])
			{
				min = j;
			}
		}
		if (min != i)
		{
			SwapNum(chaosData[min], chaosData[i]);
		}
	}

	cout << "排序后数据为:" << endl;
	for (int i = 0; i < len; ++i)
	{
		cout << chaosData[i] << " ";
	}
}

// 2.1堆排序算法
void HeapSort(int chaosData[], int len)
{
	for (int i = len / 2 - 1; i >= 0; i--)
	{
		adjust(chaosData, len, i);
		cout << endl;
		cout << "第" << i << "个结点" << endl;
		for (int i = 0; i < len; ++i)
		{
			cout << chaosData[i] << " ";
		}
		cout << endl;

	}
	for (int i = len - 1; i >= 1; i--)
	{
		SwapNum(chaosData[0], chaosData[i]);
		adjust(chaosData, i, 0);
		cout << "第" << i << "个结点" << endl;
		for (int i = 0; i < len; ++i)
		{
			cout << chaosData[i] << " ";
		}
		cout << endl;
	}

	cout << "排序后数据为:" << endl;
	for (int i = 0; i < len; ++i)
	{
		cout << chaosData[i] << " ";
	}
}
// 2.2 堆排序算法,其中的调整函数,小堆顶
void adjust(int chaosData[], int len, int index)
{
	int left = 2 * index + 1;
	int right = 2 * index + 2;
	int minId = index;
	if (left < len && chaosData[minId] < chaosData[left])
	{
		minId = left;
	}
	if (right < len && chaosData[minId] < chaosData[right])
	{
		minId = right;
	}
	if (minId != index)
	{
		SwapNum(chaosData[minId], chaosData[index]);
		adjust(chaosData, len, minId);
	}


}

 

五、插入排序之~~直接插入排序

从前到后,循环遍历,依次将数据纳入排序队列,第一次对前2个数据排序,第二次完成前3个数据排序,第N-1次完成前N个数据排序(外循环)

每次外循环选出数据,这些数据已经排好序,并将下一个数据插入到有序表中合适位置;将待插入数据依次向前遍历,直至找到比它更小的数据,完成插入。

六、插入排序之~~希尔排序

先将序列分组排序,得到的序列基本有序,即小的关键字基本在前,大的关键字基本在后。对基本有序的序列进行直接插入排序,可以增加排序效率。

比如10个元素:【1 2 3 4 5 6 7 8 9 10】

第一次分组情况:【1 6】【2 7】【3 8】【4 9】【5 10】  增量为 5

第二次分组情况:【1 3 5 7 9】【2 4 6 8 10】                     增量为2

第三次分组情况:【1 2 3 4 5 6 7 8 9 10】                           增量为1

//插入排序
//直接插入排序 和 希尔排序
#include <iostream>
#include <vector>
#include <ctime>

using namespace std;

void InsertSort(vector <int> chaosData, int len); //1.直接插入排序
void ShellSort(vector <int> chaosData, int len);  //2.希尔排序

int main()
{
	int len = 10;
	srand((unsigned)time(NULL));
	cout << "功能:对数据从大到小排序\n" << endl;
	vector <int> chaosData;
	for (int i = 0; i != len; ++i)
	{
		chaosData.push_back(rand() % 100); //产生0~100的整型数据
	}
	cout << "排序前数据为:" << endl;
	for (auto c : chaosData)
	{
		cout << c << " ";
	}

	cout << endl << "1.直接插入排序:" << endl;
	clock_t clockInsertB = clock();
	InsertSort(chaosData, len);
	clock_t clockInsertE = clock();
	cout << "\n第1种方法运行时间为:" << (double)(clockInsertE - clockInsertB)  << "毫秒" << endl;

	cout << endl << "2.希尔排序:" << endl;
	cout << "排序前数据为:" << endl;
	for (auto c : chaosData)
	{
		cout << c << " ";
	}
	clock_t clockShellB = clock();
	ShellSort(chaosData, len);
	clock_t clockShellE = clock();
	cout << "\n第2种方法运行时间为:" << (double)(clockShellE - clockShellB) << "毫秒" << endl;

	system("pause");
	return 0;
}

// 1.直接插入排序
void InsertSort(vector <int> chaosData, int len)
{
	int waitInsert; //需要插入的数据,首次从第1个数据开始,和第0个数据进行比较
	int compPosi;   //表示插入到哪些数据中,和哪些数据需要比较
	for (waitInsert = 1; waitInsert != len; ++waitInsert)
	{
		int insData = chaosData[waitInsert];  //待插入数据,作为临时变量,最后将该数据插入到合适位置;
		compPosi = waitInsert - 1;

		// while要注意一点:A&&B运算符,若A为假,则无需判断B,表达式为假;
		// 因此,下式中&&左右表达式不能互换,否则会出现调用chaosData[-1],越界出错;
		// 用insData 和 compPosi位置的数据进行比较,若insData更小,则将compPosi位置的数据向后移动;
		while ((compPosi >= 0) && (insData < chaosData[compPosi])  )
		{
			chaosData[compPosi + 1] = chaosData[compPosi]; //数据后移
			compPosi--;
		}
		chaosData[compPosi+1] = insData; // 直到insData不比compPosi处的数据小,将insData赋值为compPosi+1处的数据

		cout << "\n第" << waitInsert << "次排序后:" << endl;
		for (auto c : chaosData)
		{
			cout << c << " ";
		}
	}
}

// 2.希尔排序
void ShellSort(vector <int> chaosData, int len)
{
	int groupNum = 0; // 分组后,组内元素的位置增量,也为组数,初始化为0;
	int begNum = 0;
	int loopNum = 0;
	for (groupNum = int(len / 2);groupNum >= 1;groupNum = int(groupNum / 2))
	{
		loopNum = 1;
		// 最外层的循环实现了不同的分组情况
		// 第二层的循环,需要分别对每个分组分别进行插入排序
		for (begNum = groupNum; begNum != len; begNum++)
		{
			int insrtNum = chaosData[begNum]; //待插入的数据
			int compPosi = begNum - groupNum; //用于比较的数据
			while ((compPosi >= 0) && insrtNum < chaosData[compPosi])
			{
				chaosData[compPosi + groupNum] = chaosData[compPosi];
				compPosi = compPosi - groupNum;
			}
			chaosData[compPosi + groupNum] = insrtNum;
		}

		cout << "\n第" << loopNum << "次分组排序后:" << endl;
		loopNum++;
		for (auto c : chaosData)
		{
			cout << c << " ";
		}
	}

}

七、归并排序

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值