冒泡排序及优化 + 鸡尾酒排序

#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;
 
//冒泡排序1
/*
* 排序思想:
* 从第一个数开始,一次往后进行比较,若第一个数大于第二个数(第二个数大于第三个数...),则交换。
* 从而每一轮循环都能比较出最大数或最小数,放在最后确定的位置。
*/
void bubbleSort_1(vector<int>& vec)
{
	for (int i = 0; i < vec.size() - 1; ++i)   //n个数,n-1次外循环;
	{
		int loop_num = 0;     //记录每次内循环的次数
		for (int j = 0; j <vec.size() - 1 - i; ++j)   //每次内循环的次数为vec.size()-1-i;每完成一次外循环,就有一个元素到达最终位置;
		{
			++loop_num;
			if (vec[j] > vec[j + 1])
			{
				swap(vec[j], vec[j + 1]);
			}
		}

		std::cout << "loop_num1 = " << loop_num << std::endl;
		
		//查看每轮排序之后的结果
		for (auto& num : vec)
		{
			std::cout << num << " ";
		}
		std::cout << std::endl;
	}


	std::cout << std::endl << std::endl;
}


//冒泡排序2
//思考?若经过某轮之后有序了,能不能马上停止呢? ———— 优化!
//优化思路:能否设置一个变量,当经过某一轮循环 但没有交换的操作,那么就说明数组已经排好序了。 
//此方法能够减少不必要的循环和比较次数!
void bubblesort_2(vector<int>& vec)
{
	int len = vec.size();
	int counts = 0;  //记录元素的交换次数

	for (int i = 0; i < len - 1; ++i)
	{
		int loop_num = 0;    //记录每轮的内循环次数
		bool flag = false;   //判断某次遍历是否有元素交换,若无元素交换,则说明数组已经有序
		for (int j = 0; j < len - 1 - i; ++j)
		{
			++loop_num;
			if (vec[j] > vec[j + 1])
			{
				++counts;
				swap(vec[j], vec[j + 1]);
				flag = true;
			}
		}

		//加上flag后,当某一次循环没有发生元素交换时,则直接结束循环;
		if (!flag)  //flag = false;说明没有元素进行交换;
		{
			break;
		}

		std::cout << "loop_num2 = " << loop_num << std::endl;
		
		//查看每轮排序之后的结果
		for (auto& num : vec)
		{
			std::cout << num << " ";
		}

		std::cout << std::endl;
	}

	std::cout << std::endl << std::endl;
}


//还能不能再优化呢?
//控制内循环的比较次数,每当一轮循环后,记录最后一次交换的索引位置j。
//(说明这个位置的后面,已经排好序了。那么在进行下一轮外循环时,就不需要比较这个位置及往后的数了)。
void bubblesort_3(vector<int>& vec)
{
	int len = vec.size();
	int p_j = len - 1;
	int p_tmp = -1;

	for (int i = 0; i < len - 1; ++i)
	{
		bool flag = false;   //判断某次遍历是否有元素交换,若无元素交换,则说明数组已经有序
		int loop_num = 0;   //记录内循环的次数
		for (int j = 0; j < p_j; ++j)
		{
			if (vec[j] > vec[j + 1])
			{
				++loop_num;
				swap(vec[j], vec[j + 1]);
				flag = true;
				p_tmp = j;    //记录最后一次的交换位置;
			}

		}
		p_j = p_tmp;

		if (!flag)  //flag = false;说明没有元素进行交换;
		{
			break;
		}

		std::cout <<"loop_num3 = " << loop_num << std::endl; 
		
		//查看每轮排序之后的结果
		for (auto& num : vec)
		{
			std::cout << num << " ";
		}
		std::cout << std::endl;
	}


	std::cout << std::endl;
}


//自己实现的swap方法  ———— 可在不声明临时变量的基础上交换两个值!(本代码中未使用本方法!)
void my_swap(vector<int>& nums, int i, int j)
{
	if (i != j)
	{
		nums[i] ^= nums[j];
		nums[j] ^= nums[i];
		nums[i] ^= nums[j];
	}
}


//=========================== ** ===========================
/*
* 鸡尾酒排序:即双向冒泡排序(又称定向冒泡排序,是冒泡排序的一种改进);
* 1.冒泡排序是单向的 从小到大或从大到小的单向排序;
* 2.鸡尾酒排序是双向的,一端进行从小到大排序,一段进行从大到小排序;
* 3.鸡尾酒排序更加适合在大多数元素已经是有序的前提下,这样可以减少排序的回合数。
* 
* 步骤:
* 1.比较相邻的元素,若nums[i]>nums[i+1],则交换位置;
* 2.对每一对相邻的元素做同样的操作,结束后,将结尾指针移动到最大数的前一位,最后位置的元素即为数组的最大值;
* 3.从结尾开始向前比较,若nums[i]<nums[i-1],则交换位置;
* 4.对每一对相邻的元素做同样的操作,结束后,将结尾指针移动到最小数的后一位,开头位置的元素即为数组的最小值;
* 5.重复上述步骤,直到没有任何一对数字需要比较。
* 
* 总结:先找到最小的数字,把它放到第一位;然后找到最大的数字放到最后一位;
*	   然后再找到第二小的数字放到第二位,再找到第二大的数字放到倒数第二位;依此类推,直到完成排序;
*/
void cocktail_sort(vector<int>& nums)
{
	int len = nums.size();
	int l = 0, r = len - 1;

	int loop_num = 0;   //记录循环的次数

	while (l < r) {
		int flag1 = false;      //若某次没有发生交换,则置为true;
		int flag2 = false;

		// 前半轮,将最大元素放到后面
		for (int i = l; i < r; i++) 
		{
			if (nums[i] > nums[i + 1]) 
			{
				swap(nums[i], nums[i + 1]);
				flag1 = true;
			}
		}
		r--;  //已经把最大的值放到right的位置了,所以right要-1


		// 后半轮,将最小元素放到前面
		for (int j = r; j > l; j--) 
		{
			if (nums[j] < nums[j - 1]) 
			{
				swap(nums[j], nums[j - 1]);
				flag2 = true;
			}
		}
		l++;   //已经把最小的值放到left的位置了,所以left要+1
		
		if (!(flag1 || flag2))  //若无元素交换,则结束循环
		{
			break;
		}

		++loop_num;
		std::cout << "loop_num4 = " << loop_num << std::endl;
		//查看每轮排序之后的结果
		for (auto& num : nums)
		{
			std::cout << num << " ";
		}
		std::cout << std::endl;
	}
}


int main()
{
	vector<int> vec_1({ 13,22,47,92,4,34,56,23,45,567,23 });
	bubbleSort_1(vec_1);

	std::cout << std::endl << std::endl;

	vector<int> vec_2({ 1,2,3,4,5,10,6,19,7,8 });
	bubblesort_2(vec_2);

	std::cout << std::endl << std::endl;

	vector<int> vec_3({1, 2 ,3,10,4,12,5,6,11,7,8,9 });
	bubblesort_3(vec_3);

	std::cout << std::endl << std::endl;

	vector<int> vec_4({1,3,2,10,4,12,6,5,11,9,8,7 });
	cocktail_sort(vec_4);

	system("pause");
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值