罗曼蒂克是奢侈滴

生命不息,学习不止

导航

面试题:一道冒泡算法笔试题的演进史

给定N个整数,请使用冒泡算法按照从大到小的顺序排序

1.可对N个整数的某一段(连续的M整数)排序 

2.要求具有一定的可测试性

3.C#语言 

--------------------

思路:

1.冒泡算法

2.针对部分排序

3.可测试性

先上一段最简单的代码实现冒泡算法--这里错误的使用了选择排序,请参看改进版本的修正

 1         int[] list= new int[] {1, 2, 3, 4, 5};
 2         for (int i=0;i<list.Length;i++)
 3             for (int j=i+1;j<list.Length;j++)
 4             {                
 5                 if (list[i]<list[j])
 6                 {
 7                     int tmp=list[i];
 8                     list[i]=list[j];
 9                     list[j]=tmp;
10                 }
11             }
12         for (int i=0;i<list.Length;i++)
13             System.Console.Write("{0}\t",list[i]);
14         System.Console.WriteLine("");

观看上述代码,有如下发现

1)行1,主要进行数据的初始化工作,准备数据 

2)行2-11,主要实现冒泡排序算法

3)行12-14,主要是显示结果

4)行1-14,包含算法实现,调用,实现和使用糅合在一起

第一次改进:

1)数据初始化部分,其实属于调用部分,此时用的是数组,扩展性较差,这里改成List<int>,并将此步重构成函数

//初始化N个数据
void Init(List<int> list,int count)
{
    System.Random a=new Random();
    for (int i=0;i<count;i++)
        list.Add(a.Next(100));
}

这里初始化数据,主要是减少人工干预,自动产生测试数据,实际生产过程中,是需要按照实际情况,选取一些比较特殊的数据作为测试数据的.

2)冒泡排序算法实现过程部分,也可以重构成函数

 1     //实现冒泡算法——这里错误的使用了选择排序
 2     void Bubble(List<int> list)
 3     {        
 4         for (int i=0;i<list.Count;i++)
 5             for (int j=i+1;j<list.Count;j++)
 6             {                
 7                 if (list[i]<list[j])
 8                 {
 9                     int tmp=list[i];
10                     list[i]=list[j];
11                     list[j]=tmp;
12                 }
13             }    
14     }

正确的冒泡排序为

 1     void Bubble(List<int> list)
 2     {
 3         bool bFlag=false;
 4         for (int i=0;i<list.Count;i++)
 5         {
 6             bFlag=false;
 7             for(int j=list.Count-1-1 ;j>i-1;j--)
 8             {
 9                 if (list[j]<list[j+1])
10                 {
11                     int tmp=list[j+1];
12                     list[j+1]=list[j];
13                     list[j]=tmp;
14                     bFlag=true;
15                 }
16             }
17             if (!bFlag) break;
18         }
19     }

 

 

将排序的代码,重构成函数,使得算法可以非常容易进行测试,只需要将精心设计的测试数据传给函数,就可以了

3)显示结果,也是重构成函数

1 //显示结果
2 void Print(List<int> list)
3 {
4     for (int i=0;i<list.Count;i++)
5         System.Console.Write("{0}\t",list[i]);
6     System.Console.WriteLine("");
7 }

4)最终调用过程

public static void Main()
{
    List<int> list=new List<int>();
    //产生测试数据
    Init(list,8);    
    //打印测试数据
    Print(list);    
    //按照从大到小的顺序排序
    Bubble(list);
    //打印排序后的结果
    Print(list);    
}

 第二次改进:

第一次改进中,基本解决冒泡算法和可测试性的问题,但是还有一个重要问题没有解决,就是针对N个整数中的某一段连续M个数据进行排序,所以这次的改进主要集中在<冒泡排序算法实现>函数的改进

很明显,要实现这个功能,只需要,在 Bubble这个函数增加两个参数,标识出M的上下限,Bubble变成如下形式

1 void Bubble(List<int> list,int low,int high)

新的实现(注意,这里我的冒泡算法的实现是不对的,我用的是选择排序,经过一个园子里的兄弟提醒,我查过资料,发现的确用错了)

选择排序(Selection sort)

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

void Bubble(List<int> list,int low,int high)
{
    int iHigh= list.Count<high+1? list.Count : high+1 ;
    int iLow=low<0? 0 :low ;
    //System.Console.WriteLine("{0}\t{1}",iLow,iHigh);
    for (int i=iLow;i<iHigh;i++)
        for (int j=i+1;j<iHigh;j++)
        {                
            if (list[i]<list[j])//比较不一定相邻
            {
                int tmp=list[i];
                list[i]=list[j];
                list[j]=tmp;
            }
        }    
}
    

下面是更正后的冒泡排序代码

冒泡排序(BubbleSort)

依次比较相邻的两个数,将小数放在前面,大数放在后面。

 1     static void Bubble(List<int> list,int low,int high)
 2     {
 3         int iHigh= list.Count<high+1? list.Count : high+1 ;
 4         int iLow=low<0? 0 :low ;
 5         
 6         bool bFlag=false;
 7         for (int i=iLow;i<iHigh;i++)
 8         {
 9             bFlag=false;
10             for(int j=iHigh-1-1 ;j>i-1;j--)
11             {
12                 if (list[j]<list[j+1])//比较相邻
13                 {
14                     int tmp=list[j+1];
15                     list[j+1]=list[j];
16                     list[j]=tmp;
17                     bFlag=true;
18                 }
19             }
20             if (!bFlag) break;
21         }    
22     }

 

并提供一个重载函数

1 void Bubble(List<int> list)
2 {        
3     Bubble(list,0,list.Count-1);
4 }

调用:

 1 public static void Main()
 2 {
 3     List<int> list=new List<int>();
 4     //产生测试数据
 5     Init(list,8);    
 6     //打印测试数据
 7     Print(list);    
 8     //按照从大到小的顺序排序,针对序号2-5的之间的数据
 9     Bubble(list,2,5);
10     //打印排序后的结果
11     Print(list); 
12 }

至此,题目要求的目的全部达到,不过还是少了点什么,下面进行第三次改进

第三次改进:

第一次改进和第二次改进的结果,还是采用面向过程的方法,第三次改进侧重与面向对象的方法,就是封装

三个主要函数中都有List<int> list参数,这个是主要数据,我们用类来封装它,如下给出完整代码

 1 public class BubbleSort
 2 {
 3     List<int> _list;
 4     public BubbleSort()
 5     {
 6         _list=new List<int>();
 7     }
 8     public BubbleSort(List<int> list)
 9     {
10         _list=list;
11     }
12     
13     public void Sort()
14     {        
15         Sort(    _list,0,_list.Count-1);        
16     }    
17     public void Sort(int low,int high)
18     {
19         Sort(    _list,low,high);
20     }
21     //实现冒泡算法--这里错误使用选择排序,请替换为第二次改进中的正确实现 
22     public void Sort(List<int> list,int low,int high)
23     {
24         //int iHigh= list.Count<low+count? list.Count : high ;
25         int iHigh= list.Count<high+1? list.Count : high+1 ;
26         int iLow=low<0? 0 :low ;
27         //System.Console.WriteLine("{0}\t{1}",iLow,iHigh);
28         for    (int i=iLow;i<iHigh;i++)
29             for    (int j=i+1;j<iHigh;j++)
30             {                
31                 if (list[i]<list[j])
32                 {
33                     int tmp=list[i];
34                     list[i]=list[j];
35                     list[j]=tmp;
36                 }
37             }    
38     }        
39     
40     //初始化N个数据
41     public void Init(int count)
42     {
43         _list.Clear();
44         System.Random a=new Random();
45         for    (int i=0;i<count;i++)
46             _list.Add(a.Next(100));
47     }
48     //显示结果
49     public  void Print(List<int> list)
50     {
51         Print(list,0,list.Count-1,true);
52     }
53     public  void Print(List<int> list,int low,int high,bool IsNewLine)
54     {
55         int iHigh= list.Count<high+1? list.Count : high+1 ;
56         int iLow=low<0? 0 :low ;
57         
58         for    (int i=iLow;i<iHigh;i++)
59             System.Console.Write("{0}\t",list[i]);
60         if (IsNewLine)
61             System.Console.WriteLine("");
62     }
63     public void Print(int low,int high,bool IsNewLine)
64     {
65         Print(_list,low,high,IsNewLine);
66     }
67     //将排序的M个数据用红色显示
68     public void Print(int low,int high)
69     {
70         Print(0,low-1,false);
71         System.Console.ForegroundColor=ConsoleColor.Red;
72         Print(low,high,false);        
73         System.Console.ResetColor();
74         Print(high+1,_list.Count,true);
75     }
76     
77     public void Print()
78     {
79         Print(_list);
80     }
81     //for test
82     public void Test()
83     {
84         //产生测试数据
85         Init(10);    
86         //打印测试数据
87         Print();    
88         //按照从大到小的顺序排序
89         int[] iLowHigh=new int[]{4,7};
90         Sort(iLowHigh[0],iLowHigh[1]);
91         //Sort(-1,8);
92         //Sort(0,18);
93         //Sort(-1,18);
94         //打印排序后的结果
95         //Print(); 
96         Print(iLowHigh[0],iLowHigh[1]);
97     
98     }
99 }

调用代码:

1 BubbleSort bs=new BubbleSort();
2 bs.Test();

 


 

 

 

posted on 2012-11-19 12:21  simfe  阅读(2278)  评论(5编辑  收藏  举报