一、排序
关于排序,想必大家从字面意思就能理解,排序就是将一堆东西按照一定的规律摆放好位置。当然在计算机语言中,排序则是将一些数,字符,字符串等等数据按照程序员自定义的规则进行排列,而在计算机中又将排序分为两个大类:外排序和内排序。
外部排序:数据量过大时,无法全部加载到内存中,需要借助外部储存进行排序。
内部排序:又称内排序,指将需要处理的所有数据都加载到内部储存中竞选排序。
外排序我们目前很少接触,主要接触到的还是内排序,而内排序又分出了如下几个小的排序方法:
对于以上这些排序,目前我只做出简单的介绍,对于各排序以后的优化,我在之后的文章中会单独地进行描述。
首先先来讲讲交换排序中的冒泡排序
对于冒泡排序来说,顾名思义,就是像水中的气泡一样,大气泡的就往上浮,直至到达水面,然后破裂。而冒泡排序也是同理,通过最大的排序,将最大的数排到最后一位,然后第二大的数,到达次后位,以此类推…,通过多组遍历,直到将所有的数按从小到大的顺序排列出来,得到一个有序的数值序列,就将这样的排序方法称之为冒泡排序。由于冒泡排序中需要通过比较相邻两个数的大小,来判断是否需要进行交换,所以它属于交换排序。
冒泡排序的思路如下:
我们可以通过第一趟的冒泡排序的序列
int arr[] = {3,1,5,4,2}; //以这个数组为例
int temp = 0; //设置临时变量,用来进行交换时,不同值的储存
for(int j = 0;j < a.length - 1 - 0;j++) //此处的 0 为今后的i值,因为i控制着遍历的次数
{
if(a[j] > a[j+1])
{
temp = a[j+1];
a[j+1] = a[j];
a[j] = temp;
}
}
①第一趟排序过后的序列为:{1,3,4,2,5};
可以看出第一次的排序是将数组中的0号位置与1号位置的值进行了比较,通过判断,这两个值需要进行交换,所以得到了如上序列。在for循环中可以注意到a.length - 1 - 0,在 0 这个地方需要注意,因为此处今后作为i值,来控制交换排序所需要遍历的次数。
我们可以查看第二趟排序的序列
for(int j = 0;j < a.length - 1 - 1;j++) //此处 0 位置 变成了 1
{
if(a[j] > a[j+1])
{
temp = a[j+1];
a[j+1] = a[j];
a[j] = temp;
}
}
②第二趟排序过后的序列为:{1,3,2,4,5}
而第三趟排序,就已经达到了有序
for(int j = 0;j < a.length - 1 - 2;j++) //此处 1 位置 变成了 2
{
if(a[j] > a[j+1])
{
temp = a[j+1];
a[j+1] = a[j];
a[j] = temp;
}
}
③第三趟排序过后的序列为:{1,2,3,4,5}
可以看出在第三次排序过后,它将数按从小到大都依次排列好了,然后显示出来的就是一个有序的序列,所以可以从此看出规律:每次进行遍历时,范围发生了改变,第一趟排序时,j的遍历范围小于a.length - 1 - 0,第二趟排序时,j的遍历范围小于a.length - 1 - 1,第三趟排序时,j的遍历范围小于a.length - 1 - 2,…,所以第 i 趟排序,j的遍历范围应是小于a.length - 1- i;而在这个地方我们可以用一个大的for循环,把这个for循环嵌套在大的for循环之内,这样就可以达到不需人为输入去改变每次的排序,而是通过这个大的for循环将整个循环遍历。
所以完整的代码如下:
public static void BubbleSort(int a[]) {
int temp = 0;
for(int i = 0;i < a.length - 1;i++)
{
for(int j = 0;j < a.length - 1 - i;j++)
{
if(a[j] > a[j+1])
{
temp = a[j+1];
a[j+1] = a[j];
a[j] = temp;
}
}
}
}
虽然说它在第三次时,就将这个整数序列排好序了,可是它真正的排序次数可是大于3次的,那么怎么让这个算法,不会浪费多余的次数,而有效地进行呢?
我们可以在一开始设置一个标志位flag,来判断是否进行了交换,如果进行了交换,它就发生改变,来反馈数之间进行了交换,若没改变,则结束循环,来达到减少非必要循环的次数。可在for循环里,加入一个判断flag是否改变。
具体如下:
public static void BubbleSort(int a[]) {
int temp = 0;
int flag = 0;
for(int i = 0;i < a.length - 1;i++)
{
for(int j = 0;j < a.length - 1 - i;j++)
{
if(a[j] > a[j+1])
{
temp = a[j+1];
a[j+1] = a[j];
a[j] = temp;
flag = 1;
}
}
if(flag == 0)
{
break;
}
else
{
flag = 1;
}
}
}
也可以在 i 的那一层for循环中,设置flag,但是你在进行每一次for循环时,都会创造一个flag的空间,所以我将flag放在了最外面,而是在里面对flag进行判断。
在此给出一个实例方便理解,从键盘输入n个数,然后将这n个数进行冒泡排序(我是用Java实现的,c++和c大同小异)
package 冒泡排序;
import java.io.*;
import java.util.Arrays;
public class Main {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String n = in.readLine();
String s[] = in.readLine().split(" ");
int a[] = new int[Integer.parseInt(n)];
for(int i = 0;i < Integer.parseInt(n);i++)
{
a[i] = Integer.parseInt(s[i]);
}
BubbleSort(a);
for(int i = 0;i < a.length;i++)
{
System.out.print(a[i] + " ");
}
in.close();
}
public static void BubbleSort(int a[]) {
int temp = 0;
for(int i = 0;i < a.length - 1;i++)
{
for(int j = 0;j < a.length - 1 - i;j++)
{
if(a[j] > a[j+1])
{
temp = a[j+1];
a[j+1] = a[j];
a[j] = temp;
}
}
}
}
}
至于例子中所采用的就是冒泡排序,我对于这个排序法的理解,大致就是这样,请各位道友,如有更好的见解以及更深的理解,可私信我进行探讨。