接上篇博客,上篇博客说到了交换排序中的冒泡排序,现在来说一下交换排序中的快速排序。
(一)快速排序:
基本思想:快速排序时交换排序的一种,实质是对冒泡排序的一种改进。它的基本思想:在那个
记录中取一个记录的键值为标准,通常取第一个记录键值为基准,通过一趟排序将待排序的记录分为小于或等于这个键值和大于这个键值的两个独立部分,这是一部分的记录键值均比另一部分记录的键值小,然后,对这两个记录继续分别进行快速排序,直至最后整个序列实现排序。
事例说明:对序列45 38 66 90 88 10 25 46 运用快速排序法进行排序
快速排序过程:
[25 38 10 ] 45 [88 90 66 46]
[10 25 38 ] 45 [88 90 66 46]
[10 25 38 ] 45 [46 66 88 90]
[10 25 38 ] 45 [46 66 90 88]
代码实现:
namespace ConsoleApplication1
{
public class QuickSort
{
/// <summary>
/// 快速排序
/// </summary>
/// <param name="numbers">待排序数组</param>
/// <param name="left">数组第一个元素索引Index</param>
/// <param name="right">数组最后一个元素索引Index</param>
private static void Sort(int[] numbers, int left, int right)
{
//左边索引小于右边,则还未排序完成
if (left < right)
{
//取中间的元素作为比较基准,小于他的往左边移,大于他的往右边移
int middle = numbers[(left + right) / 2];
int i = left - 1;
int j = right + 1;
while (true)
{
while (numbers[++i] < middle) ;
while (numbers[--j] > middle) ;
if (i >= j)
break;
Swap(numbers, i, j);
}
Sort(numbers, left, i - 1);
Sort(numbers, j + 1, right);
}
}
/// <summary>
/// 交换元素值
/// </summary>
/// <param name="numbers">数组</param>
/// <param name="i">当前左边索引</param>
/// <param name="j">当前右边索引</param>
private static void Swap(int[] numbers, int i, int j)
{
int number = numbers[i];
numbers[i] = numbers[j];
numbers[j] = number;
}
public static void Main()
{
//定义数组
int[] arr = new int[10];
//生成随机数
Random rdm = new Random();
Console.WriteLine("排序前:");
for (int i = 0; i < 10; i++)
{
arr[i] = rdm.Next(0, 100);
Console.Write(arr[i] + " , ");
}
Console.WriteLine("");
Console.WriteLine("排序后:");
//调用快速排序法对进行生成的随机数组进行排序
Sort(arr, 0, arr.Length - 1);
StringBuilder temp = new StringBuilder();
for (int i = 0; i < arr.Length; i++)
{
temp.Append(arr[i].ToString() + ",");
}
Console.WriteLine(temp.ToString().Substring(0, temp.Length - 1));
Console.ReadLine();
}
}
}
(二)选择排序之直接选择排序:
基本思想:在第i次选择操作中,通过n-i次键值的比较,从n-i+1中选出键值最小的记录,并和第i个记录交换。
事例说明:对序列45 38 66 90 88 10 25 53运用直接选择排序进行排序。
第一次选择排序,待排序列(45 38 66 90 88 10 25 53)找出其中最小值10,和序列第一位的45进行交换,结果为:
10 38 66 90 88 45 25 53
第二次选择排序,待排序列(38 66 90 88 45 25 53)找出除10之外最小的25和第二位的38进行交换,结果为:
10 25 66 90 88 45 38 53
同理可得,第三次选择排序待排序列(66 90 88 45 38 53):
10 25 38 90 88 45 66 53
第四次选择排序待排序列(90 88 45 66 53):
10 25 38 45 88 90 66 53
第五次选择排序待排序列(90 88 66 53):
10 25 38 45 53 90 66 88
第六次选择排序待排序列(90 88 66):
10 25 38 45 53 66 90 88
第七次选择排序待排序列(90 88):
10 25 38 45 53 66 88 90
观察可得,直接选择排序可以这样理解:每次选择要排序的序列中最小的值,和待排序列的第一位进行交换位置,循环往复直至得出最后结果即可。
代码实现:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//定义数组
int[] arr = new int[10];
//生成随机数
Random rdm = new Random();
Console.WriteLine("排序前:");
for (int i = 0; i < 10; i++)
{
arr[i] = rdm.Next(0, 100);
Console.Write(arr[i] + " , ");
}
Console.WriteLine("");
Console.WriteLine("排序后:");
//调用直接排序法
SelectionSort(arr);
foreach (int i in arr)
{
Console.Write(i + "->");
}
Console.WriteLine();
Console.Read();
}
/// <summary>
/// 直接选择排序法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="array"></param>
public static void SelectionSort<T>(T[] array) where T : IComparable
{
int length = array.Length;
for (int i = 0; i < length; i++)
{
T min = array[i];
int minIndex = i;
for (int j = i + 1; j < length; j++)
{
if (min.CompareTo(array[j]) > 0)
{
min = array[j];
minIndex = j;
}
}
if (minIndex != i)
{
array[minIndex] = array[i];
array[i] = min;
}
}
}
}
}
对于这些算法,其中的时间和空间复杂度进行了对比,但是只是知其然,但不知其所以然,因此也就没有深入下去。这里只是根据数据结构中涉及到的相关算法进行了一下扩展和简单实现。