在阅读此博文前,请先阅读我的博文“C#排序——基类设计 “,以了解基类的结构。
关于冒泡法的概念,网上有一大堆的介绍,你可以到baidu或goole去搜索,这里不作详细解释,这遍博文的主要目标是如用C#实现冒泡排序算法。这里只简要的介绍一下冒泡排序的过程:
假设有一个IList<T>型的集合list(集合的元素为list[0]到list[n-1], n = list.Count),那么第一次遍历,从索引为0的元素开始,到索引为n-1的元素结束.在list的元素间移到时,每次都比较当前元素(假设索引号为i)与相邻元素(这种情况为下一元素i+1)的大小,如果当前元素的值小于(对于降序排列为大于)相邻元素的值,则将当前元素与其相邻元素互换:
当i=0时,比较list[0]与list[1], 如果list[0] < list[1], 则将list[0]和list[1]互换。
当i=1时,比较list[1]与list[2], 如果list[1] < list[2], 则将list[1]和list[2]互换。
...
当i=n-2时,比较list[n-2]与list[n-1],如果list[n-2] < list[n-1],则将list[n-2]与list[n-1]互换。
显然经过第一轮遍历后,list[n-1]为list集合中值最大(对于降序排列为最小)的元素。好了,list[n-1]的位置已经排好了,下一轮遍历从list[0]开始,到List[n-2]结束。即:
第1轮遍历,从list[0]开始,到list[n-1]结束,遍历结束后,list[n-1]的位置确定了。
第2轮遍历,从list[0]开始,到list[n-2]结束,遍历结束后,list[n-2]位置确定了。
...
第n-1轮遍历,从list[0]开始,到list[1]结束,遍历结束后,list[1]位置确定了。
第n轮遍历,就剩下list[0]一个元素了,其位置当然也就确定了,因此只根本就没必要第n轮遍历了,只需要n-1次遍历即可。
好了,废话少说,将上面的转变成程序,得到我们的冒泡法排序器BubbleSort的代码:
- public class BubbleSorter : Sorter
- {
- public override void Sort<T>(IList<T> list, CompareDelegate<T> compare)
- {
- for ( int endIndex = list.Count - 1; endIndex > 0; endIndex--)
- {
- for ( int index = 0; index < endIndex; index++)
- {
- if (compare(list[index], list[index + 1]) > 0) //list[index] > list[index + 1]
- {
- SwapListItem(list, index, index + 1); //调用基类的SwapListItem方法交换list[index]和list[index + 1]
- }
- }
- }
- }
- }
其中SwapListItem是其类Sorter的静态方法,用于换list中的两个元素。
现在可以用代码测试排序是否正确:
- int [] array = { 3, 7, 2, 1 };
- Sorter sorter = new BubbleSorter();
- sorter.Sort(array);
- foreach ( int i in array)
- {
- Console.Write(i + " " );
- }
怎么样?没问题吧。是不是很简单?现在还不高兴得太早,程序虽然没问题,但是效率不太高。如果我们在排序过程中发现list已经排好序了,就没必要傻傻地地继续扫描了。怎么判断list有没有排序?很简单,如果在一轮遍历过程中,没有发生元素交换,那么list就是已经排好序了。好了,现在得到BubbleSorter的最终版本:
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace CYB.DataStruct.Sorting
- {
- /// <summary>
- /// 作者 : cyb
- /// 发表时间 : 2008-9-8
- /// qq : 13101908
- /// e-mail : hustcyb@gmail.com
- /// </summary>
- public class BubbleSorter : Sorter
- {
- public override void Sort<T>(IList<T> list, CompareDelegate<T> compare)
- {
- base .Sort(list, compare);
- bool sorted = false ; //判断list是不已经排好序的布尔值
- for ( int endIndex = list.Count - 1; endIndex > 0 && !sorted; endIndex--) //判断有没有发生元素交换,没有则退出循环
- {
- sorted = true ;
- for ( int index = 0; index < endIndex; index++)
- {
- if (compare(list[index], list[index + 1]) > 0)
- {
- SwapListItem(list, index, index + 1);
- sorted = false ;
- }
- }
- }
- }
- }
- }