排序算法无论是在平时生活中还是在ACM-ICPC中都比较常用,也很重要。毕竟,在真正的数据处理过程中如果提前对数据进行有效而良好的排序,那么数据处理起来将会变得比较简洁。这里给大家介绍几个常用的排序算法。
一、插入排序:
插入排序的过程有一些类似于打扑克。相信绝大多数打过扑克的朋友都有这样的习惯,每抓一张牌,就要结合手中已有的牌进行分门别类并且按照一定的顺序进行排列。这样,在真正开始打牌的时候由于牌面比较规整,打起牌来会比较容易。我们结合具体实例,看看插入排序的过程是不是很像打扑克时抓牌时的情形:
例如:有这么一个数组,里面存了这样几个元素:5、9 、4 、2、 3 、10.。 我们用“{ }”代表整个集合,即整副扑克牌。用“ ()”代表已经排好顺序的牌,相当于抓在你手中的牌。
首先,抓牌的时候肯定是从头开始抓,你首先抓到了 5 这张牌。于是5 这张牌就在你的手中了。所以结果为{(5),9 ,4 ,2 ,3 ,10}。(初始状态)
然后,你抓下一张牌,抓到了9这张牌,与你手中已有的牌比较之后发现9比5大,所以排在5的后面,此时5,9两张牌就都在你手里了。结果为{(5,9),4 ,2 ,3 ,10}。(第一趟排序)
再往下,你抓到了4这张牌,与你手中已有的牌比较之后发现:4比5小,于是排在了最前面,结果为:{(4 ,5 ,9),2, 3, 10}。(第二趟排序)
再往下,你抓到了2这张牌,与你手中已有的牌比较之后发现:2比4小,于是2排在了最前面,结果为:{(2,4, 5, 9),3 ,10}。(第三趟排序)
再往下,你抓到了3这张牌,与你手中已有的牌比较之后发现:3大于2而小于4,于是排在2和4之间,结果为:{(2, 3, 4, 5, 9),10}。(第四趟排序)
最后,你抓到了最后一张牌10,与你手中已有的牌比较之后发现:它是最大的,于是排在最后面,结果为:{(2, 3, 4, 5, 9, 10)}。(第五趟排序)
排序结束。
大家可以自己多举几个类似的例子,多试几下就会发现,如果一个数组中有n个元素要进行排序,那么用插入排序算法,你需要进行n-1趟排序就能完成排序。插入排序在数据量较小的情况下比较实用,效率较高。
代码:
#include<iostream>
using namespace std;
///插入排序,从a[0]开始储存数据
void insertSort(int a[],int n) ///a[]代表储存数据的数组,n代表有几个元素需要排序
{
int key = 0,i = 1,j;
while(i<n)
{
key = a[i]; ///key为临时变量,用于存储当前变量a[i];
j = i-1;
while(j>=0 && key<a[j]) ///将当前元素放到正确的位置;
{
a[j+1] = a[j];
j = j-1;
}
a[j+1] = key; ///找到正确位置后,将当前元素放到j+1的位置
i++;
}
}
二、冒泡排序
现实生活中,水中气泡的重量越轻,就越容易浮上去,冒泡排序的原理类似,我们让较小的数字“浮上去”,让较大的数字“沉下去”。冒泡排序的基本思想是:扫描所有的数据,两两进行比较,若有违反轻气泡在上、重气泡在下原则的情况,则将这两个数字进行位置交换,让重气泡下沉,轻气泡上浮。
冒泡排序分为两个主要步骤:相邻元素的比较和元素位置的交换。于是,在具体代码实现的过程中,我们就依照这两个步骤展开,我们可以写两个函数,其中一个为swap()函数,用来进行元素的交换操作;另一个为bubbleSort()函数,是整个冒泡排序算法的核心。我们设置一个flag变量,在每趟排序开始的时候,将其设置为0,一旦本趟排序发生了元素的交换,则flag的值变为1 。 有元素交换,说明排序还没有完成,否则排序完成,进而,我们知道,冒泡排序结束的标志是:已经扫描了所有的元素,并且flag的值为1 。
#include<iostream>
using namespace std;
void Swap(int* a, int* b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void bubbleSort(int a[], int n)
{
int flag;
int i = 1;
int j;
do
{
for(j=0;j+1<n;j++)
{
if(a[j]>a[j+1])
{
Swap(&a[j],&a[j+1]);
flag = 1;
}
}
i++;
}while(i<n&&1==flag);
}