关于Array.Sort效率问题

最近好不容易抽出点时间对《华容道》的程序做了番调整,发现程序的性能瓶颈居然在Array.Sort上面!经过调整后,程序运行时间缩短了1秒(河北石家庄李智广编写的华容道全能版V1.1第19关)!

微软的System.Array类提供了一个静态方法Sort,可以很方便的对一维数据进行排序。对于比较懒的我,一向直接使用Array.Sort完成对数组的排序。今天才发现原来Array.Sort存在严重的效率问题。先来看一段使用Array.Sort进行自定义排序的例子。

None.gif using  System;
None.gif
using  System.Collections;
None.gif
None.gif
public   class  DataElement
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  
public int value;
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public DataElement() dot.gif{}
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public DataElement(int value) dot.gifthis.value = value; }
ExpandedBlockEnd.gif}

None.gif
None.gif
public   class  DataElementComparer : IComparer
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  
public int Compare(object x, object y)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    
return ((DataElement)x).value.CompareTo(((DataElement)y).value);
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
None.gif
public   class  Client
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  
public static void Main() 
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif    
int[] a = dot.gif{5,8,3,6,9};
InBlock.gif    DataElement[] d 
= new DataElement[5];
InBlock.gif
InBlock.gif    
for(int i=0; i<5; i++)
InBlock.gif      d[i] 
= new DataElement(a[i]);
InBlock.gif
InBlock.gif    Array.Sort(d, 
new DataElementComparer());
InBlock.gif
InBlock.gif    
for(int i = 0; i<5; i++)
InBlock.gif      Console.Write(d[i].value 
+ "");
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

注意,在上面的例子中,为了实现自定义类(DataElement)的排序,我设计了一个DataElementComparer类,实现了System.Collections.IComparer接口。这样,在应用Array.Sort方法时,同时提供要排序的数组以及DataElementComparer的一个实例,便可以进行排序了。

但需要注意的是,在.net 2003中没有泛型的支持,所以IComparer接口在定义时,Compare方法接收的参数是object类型。因此,在进行比较时需要对值类型数据进行反复Box和UnBox操作,而对于引用类型则反复进行UpCast和DownCast操作,严重影响了效率!

在C# 2.0规范中提供了泛型机制,我想IComparer接口应当重新进行了定义,Array.Sort的效率应当比现在要强很多。我后来将《华容道》中应用Array.Sort的地方改为了使用“快速排序法”代码,效率一下子上去了。解题时间从原来的7.4秒缩短到了6.4秒,可是不小的进步呀!快速排序法代码如下(具体算法可以参考《数据结构》中的相关章节):

None.gif using  System;
None.gif
None.gif
public   class  DataElement
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  
public int value;
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public DataElement() dot.gif{}
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public DataElement(int value) dot.gifthis.value = value; }
ExpandedBlockEnd.gif}

None.gif
None.gif
public   class  QuickSortArray
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  
public DataElement[] list;
InBlock.gif
InBlock.gif  
public void quickSort()
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    recQuickSort(
0, list.Length - 1);
ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
private void recQuickSort(int first, int last)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    
int pivotLocation;
InBlock.gif
InBlock.gif    
if(first < last)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      pivotLocation 
= partition(first, last);
InBlock.gif      recQuickSort(first, pivotLocation 
- 1);
InBlock.gif      recQuickSort(pivotLocation 
+ 1, last);
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
private int partition(int first, int last)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    DataElement pivot;
InBlock.gif    
int index, smallIndex;
InBlock.gif
InBlock.gif    swap(first, (first 
+ last) / 2);
InBlock.gif    pivot 
= list[first];
InBlock.gif    smallIndex 
= first;
InBlock.gif
InBlock.gif    
for(index = first + 1; index <= last; index++)
InBlock.gif      
if(list[index].value < pivot.value)
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif        smallIndex
++;
InBlock.gif        swap(smallIndex, index);
ExpandedSubBlockEnd.gif      }

InBlock.gif
InBlock.gif    swap(first, smallIndex);
InBlock.gif    
return smallIndex;
ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
private void swap(int first, int second)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    DataElement temp;
InBlock.gif
InBlock.gif    temp 
= list[first];
InBlock.gif    list[first] 
= list[second];
InBlock.gif    list[second] 
= temp;
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif  
None.gif
public   class  Client
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  
public static void Main()
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif    
int[] a = dot.gif{424301320313240412123};
InBlock.gif
InBlock.gif    QuickSortArray qs 
= new QuickSortArray();
InBlock.gif    qs.list 
= new DataElement[12];
InBlock.gif
InBlock.gif    
for(int i=0; i<12; i++)
InBlock.gif      qs.list[i] 
= new DataElement(a[i]);
InBlock.gif
InBlock.gif    qs.quickSort();
InBlock.gif
InBlock.gif    
for(int i=0; i<12; i++)
InBlock.gif      Console.WriteLine(qs.list[i].value 
+ "");  
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值