Fork me on GitHub

数据结构---排序(2)

三、交换排序

3.1冒泡排序

思路:冒泡排序,把数据看做气泡,扫描到轻气泡,使其向上“漂浮”。如此反复,直到有序。

步骤:1.外层循环,进行n-1趟排序。

        2.内层循环,使重气泡上浮。

描述:

设计:

using   System;
public class myBufferSort
{
private int[] mat;
public myBufferSort(int[] table)
{
mat = new int[table.Length]; table.CopyTo(mat, 0); // 数组拷贝
}
public void bufferSort()
{
for (int i = 0; i < mat.Length - 1; i++) // n-1趟排序后,使其有序
for (int j = 0; j < mat.Length - i - 1; j++) // 扫描数据
if (mat[j] > mat[j + 1]) // 发现重气泡就使其下沉
swap(j, j + 1); // 交换数据
}
public void bufferSortCool() // 改进行冒泡排序
{
bool exchange = true;
int index = 0, i = 0, j = 0;
while (exchange && i < mat.Length - 1)
{
exchange = false; j = index;
while (j < mat.Length - i - 1)
{
if (mat[j] > mat[j + 1])
{
swap(j, j + 1);
exchange = true;
}
// j ++ ;
if (!exchange && mat[j] < mat[j + 1])
index++;
j++;
} i++;
}
}
public void swap(int i, int j)
{
int temp; temp = mat[i]; mat[i] = mat[j]; mat[j] = temp;
}
public void output()
{
for (int i = 0; i < mat.Length; i++)
Console.Write(mat[i] + ""); Console.WriteLine();
}
public static void Main()
{
Random rom = new Random();
int[] table = new int[10];
for (int i = 0; i < table.Length; i++)
table[i] = rom.Next(1, 99); // 生成随数放入数组。
myBufferSort mbs = new myBufferSort(table); mbs.output();
// mbs.bufferSort();
mbs.bufferSortCool();
mbs.output();
}
}



     此排序还可以改进,若在某一趟中未发现气泡位置的交换,则说明待排序的无序区中所有气泡均匀满足轻者在上,重者下的原则,
因此,排序已经终止。为此,引入一个布尔变量exchange,来控制循环条件。bufferSortCool()就是改进版。

    2012.01.15 今天在温习排序的时候发现代码中的一个小bug,冒泡排序的改进版中,如果数组当前是有序的,那么将报错,数组超出下标。其实这个问题很小,

只是j++的位置出现了问题,在mat[j]<mat[j+1]之前进行了j++操作,导致下标出现越界问题。但是反映的问题确不小,因为在无序的情况下,这段代码是没有任何问题的。有2点总结,1是在学习算法时,自己理解并不是非常透彻。2是在做测试时没有做到条件覆盖。引此为戒!

 

3.2快速排序

快速排序是排序中算法比较麻烦的,自己到现在还没能完全掌握。

它采用分治策略,所谓分治,就是将原问题分解为若干个规模更小但结构与原问题相似的子问题,递归地解决这些子问题,然后将子问题的解组合为原问题的解。

思路:在待排序列中任意选择一个值作为基准值,由序列的两端交替比较、交换,使得所有基准值小的元素处于序列的左端,比基准值大的数据处于右端,这样就划分为两个子序,再对两个子序列分别进行同样的操作,知道子序列的长度为一时,排序完成。

步骤:划分算法--1.设置两个指针i和j,他们的初值分别为区间下界和上界;选取无序区的第一个记录mat[i]作为基准值,并将它保存到比变量pivot中。

                      2.令j自high起向左扫描,找到第一个关键字小于pivot的记录,将mat[j]移至i所指的位置上。然后令i指针自i+1开始向右扫描,直至
                         找到第一个关键字大于pivot的记录,将mat[i]移至j所指的位置上。重复执行,使两端向中间靠拢,直至i=j时,i便是pivot最终的
                         位置,也就完成了一次划分。

描述:

设计:

using   System;
public class myQuickSort
{
private int[] mat;
public myQuickSort(int[] table)
{
mat = new int[table.Length]; table.CopyTo(mat, 0); // 数组拷贝
}
public void quickSort(int low, int high) // 快排
{
int pivotpos; // 划分后的基准记录的位置
if (low < high)
{
pivotpos = partition(low, high); // 对low,high划分
quickSort(low, pivotpos - 1); // 对做区间递归排序
quickSort(pivotpos + 1, high); // 对右区间递归排序
}
}
public int partition(int i, int j) // 对mat[low..high]做划分
{
int pivot = mat[i]; // 用区间的第一个记录作为基准值
while (i < j) // 从区间两端交替向中间扫描,直至i=j
{
while (pivot < mat[j] && i < j) // 从右向左,扫描到第一个关键字小于pivot的记录
j--; if (i < j) // 交换mat[i]和mat[j],指针i加1
mat[i++] = mat[j]; while (pivot > mat[i] && i < j) // 从左向右,扫描到第一个关键字大雨pivot的记录
i++; if (i < j) // 交换mat[j]和mat[i],指针j加1
mat[j--] = mat[i];
} mat[i] = pivot; // 基准记录已被最后定位
return i;
}
public void output()
{
for (int i = 0; i < mat.Length; i++)
Console.Write(mat[i] + ""); Console.WriteLine();
}
public static void Main()
{
Random rom = new Random(); int[] table = new int[10];
for (int i = 0; i < table.Length; i++) table[i] = rom.Next(1, 99); // 生成随数放入数组。
myQuickSort mqs = new myQuickSort(table); mqs.output(); mqs.quickSort(0, table.Length - 1);
mqs.output();
}
}



 

posted @ 2009-02-06 00:00  idoku  阅读(205)  评论(0编辑  收藏  举报