第三章基础排序算法
对计算机中所存储的数据最普遍的两种操作就是排序和查找。本章会介绍有关数据排序和查找的基础算法。这些算法仅依赖数组作为数据结构,而且所采用的“高级”编程技术只是递归。本章还介绍了用来非正式分析不同算法的速度与效率的方法,此飞方法贯串全书。
3.1排序算法
3.1.1数组类测试环境
为了检验这些算法,首先需要构造一个可以实现并测试算法的测试环境。这里将构造一个类来封装数组处理的一些常规动作。
class CArray
{
private int[] arr;
private int upper;
private int numElements;
public CArray(int size)
{
arr = new int[size];
upper = size - 1;
numElements = 0;
}
public void Insert(int item)
{
arr[numElements] = item;
numElements++;
}
public void DisplayElements()
{
for (int i = 0; i <= upper; i++)
Console.Write(arr[i] + " ");
}
public void Clear()
{
for (int i = 0; i <= upper; i++)
arr[i] = 0;
numElements = 0;
}
static void Main()
{
CArray nums = new CArray(50);
for (int i = 0; i <= 49; i++)
nums.Insert(i);
nums.DisplayElements();
Console.ReadKey();
}
}
在保留CArray类以便开始检测排序和查找算法之前,还是先来讨论一下在CArray类对象内实际存储数据的问题。为了更有效地说明不同排序算法是如何运行的,数组内数据需要随机放置,最好的实现方法就是使用随机数生成器来给数组的每个元素进行赋值。
static void Main()
{
CArray nums = new CArray(10);
Random rnd = new Random(100);
for (int i = 0; i <10; i++)
nums.Insert(rnd.Next(0,100));
nums.DisplayElements();
}
3.1.2冒泡排序
public void BubbleSort()
{
int temp;
for (int outer = upper; outer >= 1; outer--)
{
for (int inner = 0; inner <= outer - 1; inner++)
{
if ((int)arr[inner] > arr[inner + 1])
{
temp = arr[inner];
arr[inner] = arr[inner + 1];
arr[inner + 1] = temp;
}
}
this.DisplayElements();
}
}
这里把DisplayElements()方法放置在了两个for循环之间。如果主程序按照如下形式进行修改:
static void Main()
{
CArray nums = new CArray(10);
Random rnd = new Random(100);
for (int i = 0; i < 10; i++)
{
nums.Insert(rnd.Next(0, 100));
}
Console.WriteLine("Before sorting");
nums.DisplayElements();
Console.WriteLine("During sorting");
nums.BubbleSort();
Console.WriteLine("After sorting");
nums.DisplayElements();
}
下面是这段程序的输出结果:
3.1.4选择排序
这种排序是从数组的起始处开始,把第一个元素与数组中其他元素进行比较。然后将最小的元素放置在第0个位置上,接着再从第一个位置开始再次进行排序操作。这种操作会到除最后一个元素外的每一个元素都作为新循环的起始点操作过后才终止。
public void SelectionSort()
{
int min, temp;
for (int outer = 0; outer <= upper; outer++)
{
min = outer;
for (int inner = outer + 1; inner <= upper; inner++)
{
if (arr[inner] < arr[min])
min = inner;
}
temp = arr[outer];
arr[outer] = arr[min];
arr[min] = temp;
this.DisplayElements();
}
}
3.1.5插入排序
public void InsertionSort()
{
int inner, temp;
for (int outer = 1; outer <= upper; outer++)
{
temp = arr[outer];
inner = outer;
while (inner > 0 && arr[inner - 1] >= temp)
{
arr[inner] = arr[inner - 1];
inner -= 1;
}
arr[inner] = temp;
this.DisplayElements();
}
}
这个输出清楚地表明插入排序不是通过交换来处理的,而是通过把较大的数组元素向右移动来为数组左侧较小元素留在空间的方式进行操作的。
3.2基础排序算法的时间比较
这里用Timing类来比较三种算法,根据他们对庞大数字集合进行排序时所花费的时间【判定出是否有算法会与众不同
class Timing
{
TimeSpan duration;
public Timing()
{
duration = new TimeSpan(0);
}
public void stopTime()
{
duration = Process.GetCurrentProcess().TotalProcessorTime;
}
public void startTime()
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
public TimeSpan Result()
{
return duration;
}
}
class CArray
{
private int[] arr;
private int upper;
private int numElements;
public CArray(int size)
{
arr = new int[size];
upper = size - 1;
numElements = 0;
}
public void Insert(double item)
{
arr[numElements] =(int)item;
numElements++;
}
public void DisplayElements()
{
for (int i = 0; i <= upper; i++)
Console.Write(arr[i] + " ");
Console.WriteLine();
}
public void Clear()
{
for (int i = 0; i <= upper; i++)
arr[i] = 0;
numElements = 0;
}
static void Main()
{
Timing sortTime = new Timing();
Random rnd = new Random(100);
int numItems = 5000;
CArray theArray = new CArray(numItems);
for (int i = 0; i < numItems; i++)
{
theArray.Insert(rnd.NextDouble()*100);
}
sortTime.startTime();
theArray.SelectionSort();
sortTime.stopTime();
Console.WriteLine("Time for Selection sort:" + sortTime.Result().TotalMilliseconds);
theArray.Clear();
for (int i = 0; i < numItems; i++)
{
theArray.Insert(rnd.NextDouble() * 100);
}
sortTime.startTime();
theArray.InsertionSort();
sortTime.stopTime();
Console.WriteLine("Time for Insertion sort:" + sortTime.Result().TotalMilliseconds);
theArray.Clear();
for (int i = 0; i < numItems; i++)
{
theArray.Insert(rnd.NextDouble() * 100);
}
sortTime.startTime();
theArray.BubbleSort();
sortTime.stopTime();
Console.WriteLine("Time for Bubble sort:" + sortTime.Result().TotalMilliseconds);
}
public void BubbleSort()
{
int temp;
for (int outer = upper; outer >= 1; outer--)
{
for (int inner = 0; inner <= outer - 1; inner++)
{
if ((int)arr[inner] > arr[inner + 1])
{
temp = arr[inner];
arr[inner] = arr[inner + 1];
arr[inner + 1] = temp;
}
}
}
}
public void SelectionSort()
{
int min, temp;
for (int outer = 0; outer <= upper; outer++)
{
min = outer;
for (int inner = outer + 1; inner <= upper; inner++)
{
if (arr[inner] < arr[min])
min = inner;
}
temp = arr[outer];
arr[outer] = arr[min];
arr[min] = temp;
}
}
public void InsertionSort()
{
int inner, temp;
for (int outer = 1; outer <= upper; outer++)
{
temp = arr[outer];
inner = outer;
while (inner > 0 && arr[inner - 1] >= temp)
{
arr[inner] = arr[inner - 1];
inner -= 1;
}
arr[inner] = temp;
}
}
}
当数组元素量增加到10000个的时候,确实能出数组大小对三种排序算法的影响
尽管选择排序始终比其他这两种算法快出许多倍,但是所有这三种排序算法的性能还是相当低的