关闭

排序算法之冒泡排序

标签: 冒泡排序鸡尾酒排序双向冒泡排序排序数据结构
350人阅读 评论(0) 收藏 举报
分类:
冒泡排序是最基础的排序算法,是一种交换排序。
冒泡排序的方法为:对于将被排序的数组 A[1...n],从最左边或者从最右边开始依次比较相邻的两个元素,将大数放在右边,小数放在左边。
  • 从最左边开始即首先比较 A[1] 和 A[2],如果A[1] 比 A[2] 大则交换,保证大数在右边;然后比较 A[2] 和 A[3],如果 A[2] 比 A[3] 大则交换;如此继续,直到比较最后两个数。这样一轮交换过后,最右边的数一定是最大的。接着再对 A[1...n-1] 重复上一轮的交换过程,这样又得到一个最大的数放在最右边(是 A[1...n-1] 的最右边,是整个数组从最右边开始数第二的位置)。重复这样的交换过程,最大值会依次冒泡到右边,最终得到有序数组。
  • 从最右边开始实质是一样的,首先比较 A[n] 和 A[n-1],如果A[n] 比 A[n-1] 小则交换,保证小数在左边;然后比较 A[n-1] 和 A[n-2],如果 A[n-1] 比 A[n-2] 小则交换;如此继续,直到比较最后两个数。这样一轮交换过后,最左边的数一定是最小的。接着再对 A[2...n] 重复上一轮的交换过程,这样又得到一个最小的数放在最左边(是 A[2...n] 的最左边,是整个数组从最左边开始数第二的位置)。重复这样的交换过程,最小值会依次冒泡到左边,最终得到有序数组。

上面所说的两种方法实质是一样的,代码实现上只是数值比较的顺序不一样而已。

下面给出第一种方法的排序代码:

#include <iostream>
using namespace std;

// 数值交换
void swap(int& a, int& b)
{
	int t = a;
	a = b;
	b = t;
}

// 冒泡排序
void BubbleSort(int *arr, int len)
{
	for (int i = 0; i < len - 1; ++i)
	{
		for (int j = 0; j < len - 1 - i; ++j)
		{
			if (arr[j] > arr[j + 1])
			{
				swap(arr[j], arr[j + 1]);
			}
		}
	}
}

int main()
{
	int arr[] = { 8, 110, 9, 3, 5, 21, 6, 11, 5, 44, 7, 2, 1, 99, 10 };
	int len = sizeof(arr) / sizeof(*arr);
	cout << "排序前: ";
	for (int i = 0; i < len; ++i)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
	BubbleSort(arr, len);	// 对数组arr进行冒泡排序
	cout << "排序后: ";
	for (int i = 0; i < len; ++i)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
	return 0;
}


运行结果如下:



第二种方法将冒泡排序改成如下即可:

void BubbleSort(int *arr, int len)
{
	for (int i = 0; i < len - 1; ++i)
	{
		for (int j = len - 1; j > i; --j)
		{
			if (arr[j] < arr[j - 1])
			{
				swap(arr[j], arr[j - 1]);
			}
		}
	}
}

这样是最基本的排序方案,但存在一个小问题,就是假如在第 i 轮比较交换前数组已经排好序了,但是它还是会进行之后的比较交换,显然这是不必要的。所以对代码进行一点改进,当某一轮比较交换发现已经排好序了就可以结束排序过程了。改进的代码如下:

#include <iostream>
using namespace std;

void swap(int& a, int& b)
{
	int t = a;
	a = b;
	b = t;
}

// 改进的冒泡排序
void BubbleSort(int *arr, int len)
{
	int tail = len - 1;
	int exchange = 1;
	while (exchange)	// 如果没有进行过交换,则已经是排好序的了,无需再进行循环比较
	{
		exchange = 0;
		for (int j = 0; j < tail; ++j)
		{
			if (arr[j] > arr[j + 1])
			{
				swap(arr[j], arr[j + 1]);
				exchange = 1;	
			}
		}
		--tail;
	}
}

还有一种改进的冒泡排序,是对要排序的数组进行双向冒泡排序,又称为鸡尾酒排序,代码如下:
#include <iostream>
using namespace std;

void swap(int& a, int& b)
{
	int t = a;
	a = b;
	b = t;
}

// 鸡尾酒排序(双向冒泡排序)
void Cocktail(int *arr, int len)
{
	int head = 0;
	int tail = len - 1;
	int exchange = 1;
	while (exchange)
	{
		exchange = 0;
		// 从左边开始比较,找出最大的元素放到右边
		for (int j = head; j < tail; ++j)
		{
			if (arr[j] > arr[j + 1])
			{
				swap(arr[j], arr[j + 1]);
				exchange = 1;
			}
		}
		--tail;
		
		// 从右边开始比较,找出最小的元素放到左边
		for (int j = tail; j > head; --j)
		{
			if (arr[j] < arr[j - 1])
			{
				swap(arr[j], arr[j - 1]);
				exchange = 1;
			}
		}
		++head;
	}
}

int main()
{
	int arr[] = { 8, 110, 9, 3, 5, 21, 6, 11, 5, 44, 7, 2, 1, 99, 10 };
	int len = sizeof(arr) / sizeof(*arr);
	cout << "排序前: ";
	for (int i = 0; i < len; ++i)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
	Cocktail(arr, len);	// 鸡尾酒排序
	cout << "排序后: ";
	for (int i = 0; i < len; ++i)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
	return 0;
}
运行结果也是一样的:


1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:52378次
    • 积分:856
    • 等级:
    • 排名:千里之外
    • 原创:36篇
    • 转载:0篇
    • 译文:0篇
    • 评论:7条
    文章分类
    最新评论