排序——简单排序

简单排序有三种,包括选择排序(Selection Sort)、冒泡排序(Bubble Sort)和插入排序(Insert Sort)。

选择排序每次都选择最小的关键码记录,直到完全排序。实质上就是起泡排序。选择排序第 i 趟选择的是数组中第 i 小的记录,并将这个记录放到数组的第 i 个位置。

特点:大部分时间都在比较,很少交换。

在寻找下一个较小的数时,需要检索整个未排序的序列,但只用一次交换即可将待排序的记录放到正确位置,这样最多要用n-1次交换。对于处理那些做一次交换花费时间较多的问题,选择排序是很有效的。比如说,元素是较长的字符串或是其他大型记录。记住选择的最小元素的位置并最后用一次交换使它到位,而不是不断的交换相邻记录以使下一最小记录到位。

//select sort
#include<iostream>
using namespace std;
void swap(int &a, int &b)
{
	/*
	when sequence has same value, XOR method is invalid.
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
	*/
	int tmp;
	tmp = a; a = b; b = tmp;
}
int main()
{
	int arr[8];
	cout << "input arr elements please." << endl;
	for (int i = 0; i < 8; i++)
	{
		cin >> arr[i];
	}
	cout << "after sorting:";
	for (int i = 0; i < 7; i++)
	{
		// select ith key
		int j = 0;
		int low = i;	// store index location
		// find mini-value, i represent mini-value location in unsorted sequence 
		for (j = 7; j > i; j--)
		{
			if (arr[j] < arr[low]) low = j;
		}
		swap(arr[j], arr[low]);
	}
	for (int i = 0; i < 8; i++)
	{
		cout << arr[i] << " ";
	}
	cout << "\n";
	system("pause");
	return 0;
}

选择排序,排8个元素,外循环7次就行了,最后一个元素肯定最大。

下面是选择排序的示例图。

有一种方法可降低各种排序算法用于交换记录所用的时间,尤其是当记录很多时,这就是使数组中的每一个元素存储指向该元素记录的指针。这种实现,交换只需要对指针所指的关键码进行操作。虽然要一些空间来存放指针,但换来的是更高的效率。

冒泡排序是一种较慢的排序,交换次数与插入排序相同,不同于插入排序,它没有较好的最佳情况执行时间。

冒泡排序,包括一个简单的for循环,第一趟的内循环从数组的底部比较到顶部,比较相邻的关键码。如果下面的key比其上邻居的key小,则将二者交换顺序。但如果不比它小,那么所有者将自动成为其上邻居,往上冒泡。

一旦遇到一个最小key,这个过程将使它像个气泡一样被推倒了数组的顶部。最小元素第一次就被排列了数组的最上面,所以就没必要再比较最上面的两个元素了。

同样每轮循环都比较的是相邻的key,但每过一轮都会在比较中少一个key。

分析冒泡排序的比较次数:不考虑数组中结点的组合情况,比较的次数总将是i,时间复杂度为1+2+3+...+n = O(n*n)。

// BubbleSort_1
#include<iostream>
using namespace std;

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

int main()
{
	int array1[8];
	cout << "请输入需要排序的值:";
	for (int i = 0; i < 8; i++)
	{
		cin >> array1[i];
	}
	cout << "排序后的值:";
	// 对数组进行冒泡排序
	for (int i = 0; i < 7; i++)
	{
		for (int j = 7; j > i; j--)
		{
			if (array1[j] < array1[j - 1]) swap(array1[j], array1[j - 1]);
		}
	}
	for (int i = 0; i < 8; i++)
	{
		cout << array1[i] << " ";
	}
	cout << endl;
	system("pause");
	return 0;
}

上面代码是冒泡排序的其中一种实现方式,还有另一种实现代码如下,

// BubbleSort_2
for (int i = 0; i < 8 - 1; i++)
{
    for (int j = 0; j < 8 - 1 - i; j++)
    {
        if (array1[j] > array1[j + 1]) swap(array1[j], array1[j + 1]);
    }
}

冒泡排序,排8个元素,外循环循环7次,每次循环可以排好一个元素

 

插入排序是逐个处理待排序的记录,每个新记录与前面已排序的子序列比较,将它插入到子序列中正确位置。

考虑第 i 个记录被处理时的情况,记录的值设为X。当X比它上面的那个值小时,它向上移动,直到遇到一个比它小或相等的值时,本次插入才完成,所以在向前就一定都比它小了。(注意一点,逆序、正序对此算法效率差别很大。)

// InsertSort
#include<iostream>
using namespace std;

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

int main()
{
	int array1[9];		// 第一个元素作为哨兵使用
	cout << "请输入需要排序的值:";
	for (int i = 1; i < 9; i++)
	{
		cin >> array1[i];
	}
	cout << "排序后的值:";

	// 对数组进行插入排序
	for (int i = 1; i < 9; i++)
	{
		//插入第i个记录
		if (array1[i] > array1[i - 1]) continue;		// 无需操作
		array1[0] = array1[i];							// 设置哨卡
		int j = 0;
		for (j = i - 1; array1[0] < array1[j]; j--)
		{
			array1[j + 1] = array1[j];
		}
		array1[j + 1] = array1[0];			// 插入到合适位置
	}
	for (int i = 1; i < 9; i++)
	{
		cout << array1[i] << " ";
	}
	cout << endl;

	system("pause");
	return 0;
}

插入排序,排8个元素,8次循环,每次外循环分别把相应元素放到前面部分的合适位置上去。

 

总结简单排序——速度慢的原因

关键的瓶颈是只比较相邻元素。此时比较和移动是一步步进行的(除选择排序),有时这些排序又叫交换排序。任何一种将比较限制在相邻两元素间进行的交换算法的平均时间代价都是O(n*n)。

  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值