First we try, then we trust

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
最近好不容易抽出点时间对《华容道》的程序做了番调整,发现程序的性能瓶颈居然在Array.Sort上面!经过调整后,程序运行时间缩短了1秒(河北石家庄李智广编写的华容道全能版V1.1第19关)!

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

using System;
using System.Collections;

public class DataElement
{
  
public int value;
  
public DataElement() {}
  
public DataElement(int value) this.value = value; }
}


public class DataElementComparer : IComparer
{
  
public int Compare(object x, object y)
  
{
    
return ((DataElement)x).value.CompareTo(((DataElement)y).value);
  }

}


public class Client
{
  
public static void Main() 
  
{
    
int[] a = {5,8,3,6,9};
    DataElement[] d 
= new DataElement[5];

    
for(int i=0; i<5; i++)
      d[i] 
= new DataElement(a[i]);

    Array.Sort(d, 
new DataElementComparer());

    
for(int i = 0; i<5; i++)
      Console.Write(d[i].value 
+ "");
  }

}

注意,在上面的例子中,为了实现自定义类(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秒,可是不小的进步呀!快速排序法代码如下(具体算法可以参考《数据结构》中的相关章节):

using System;

public class DataElement
{
  
public int value;
  
public DataElement() {}
  
public DataElement(int value) this.value = value; }
}


public class QuickSortArray
{
  
public DataElement[] list;

  
public void quickSort()
  
{
    recQuickSort(
0, list.Length - 1);
  }


  
private void recQuickSort(int first, int last)
  
{
    
int pivotLocation;

    
if(first < last)
    
{
      pivotLocation 
= partition(first, last);
      recQuickSort(first, pivotLocation 
- 1);
      recQuickSort(pivotLocation 
+ 1, last);
    }

  }


  
private int partition(int first, int last)
  
{
    DataElement pivot;
    
int index, smallIndex;

    swap(first, (first 
+ last) / 2);
    pivot 
= list[first];
    smallIndex 
= first;

    
for(index = first + 1; index <= last; index++)
      
if(list[index].value < pivot.value)
      
{
        smallIndex
++;
        swap(smallIndex, index);
      }


    swap(first, smallIndex);
    
return smallIndex;
  }


  
private void swap(int first, int second)
  
{
    DataElement temp;

    temp 
= list[first];
    list[first] 
= list[second];
    list[second] 
= temp;
  }

}

  
public class Client
{
  
public static void Main()
  
{
    
int[] a = {424301320313240412123};

    QuickSortArray qs 
= new QuickSortArray();
    qs.list 
= new DataElement[12];

    
for(int i=0; i<12; i++)
      qs.list[i] 
= new DataElement(a[i]);

    qs.quickSort();

    
for(int i=0; i<12; i++)
      Console.WriteLine(qs.list[i].value 
+ "");  
  }

}
posted on 2005-02-01 15:54  吕震宇  阅读(2923)  评论(8编辑  收藏  举报