面试题:一道冒泡算法笔试题的演进史
给定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();