c#实现的几种排序方法
1.经典排序算法 – 插入排序Insertion sort
插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕。
插入排序方法分直接插入排序和折半插入排序两种,这里只介绍直接插入排序,折半插入排序留到“查找”内容中进行。
图1演示了对4个元素进行直接插入排序的过程,共需要(a),(b),(c)三次插入。
public void Sort(int[] arr)
{
for (int i = 1; i < arr.Length; i++)
{
int t = arr[i];
int j = i;
while ((j > 0) && (arr[j - 1] > t))
{
arr[j] = arr[j - 1];//交换顺序
--j;
}
arr[j] = t;
}
}
折半排序算法是对直接插入算法的一种优化,优化的核心是:通过折半查看有序数组中间位置的数值(a)与待插入的数值(temp)的大小,如果a>=temp,则转向折半的左区间继续折半查找; 如果a<temp,则转向折半后的右区间继续折半查找。直到左右下标相同时,此时折半的下标也指向相同的位置,再做最后一次循环,最终的结果是:左右下标相差1,并且原来左侧的下标指向大于temp的位置,原来右侧的下标指向了小于temp的位置,即:array[biggerIndex] < temp < array[smallerIndex]。
//折半排序算法(传递待排数组名,即:数组的地址。故形参数组的各种操作反应到实参数组上)
private static void BinaryInsertionSortFunction(int[] array)
{
try
{
int smallerIndex = 0; //记录有序数组的起始位置
int biggerIndex = 0; //记录有序数组的终止位置
int midIndex = 0; //记录获取有序数组的中间位置(折半法的关键:折半的位置)
int temp; //记录带排的数值
for (int i = 1; i < array.Length; i++) //循环向有序数组中插入数值(i从1开始,因为操作的是同一个数组)
{
temp = array[i]; //记录待插入有序数组的数值
biggerIndex = i - 1;
//当smallerIndex==biggerIndex时,进入最后一次循环:smallerIndex指向大于temp的数组位置,biggerIndex指向小于temp的数组位置
while (smallerIndex <= biggerIndex)
{
midIndex = (smallerIndex + biggerIndex) / 2; //确定折半的位置
if(array[midIndex] >= temp) //折半位置的数值 >= temp
{
biggerIndex = midIndex - 1; //biggerIndex以midIndex为基础向前移动一位
}
else
{
smallerIndex = midIndex + 1; //smallerIndex以midIndex为基础向后移动一位
}
}
for (int j = i - 1; j >biggerIndex; j--) //将有序数组中大于temp的数值分别向后移动一位
{
array[j + 1] = array[j]; //
}
array[biggerIndex + 1] = temp; //将temp插入biggerIndex + 1,因为此时array[biggerIndex]<temp<array[smallerIndex]
}
}
catch (Exception ex)
{ }
}
2. //选择排序
public static void SelectionSort(int[] num)
{
int min, temp;
for (int i = 0; i < num.Length-1; i++)
{
min = i;
for (int j =i+1; j < num.Length; j++)
{
if (num[j] < num[min])
{
min = j;
}
}
temp = num[i];
num[i] = num[min];
num[min] = temp;
}
}
3. //冒泡排序(Bubble Sort)的基本思想是:将相邻的记录的关键码进行比较,若前面记录的关键码大于后面记录的关键码,则将它们交换,否则不交换。
public static void BubbleSort(int[] list)
{
int temp;
bool IfChanged = false;//默认没有交换数据
for (int j = 1; j <= list.Length -1; j++)
{
for (int i = 0; i <= list.Length - j -1; i++)
{
if (list[i] > list[i + 1])
{
IfChanged = true; //交换了数据
temp = list[i];
list[i] = list[i + 1];
list[i + 1] = temp;
}
}
if (IfChanged == false) break; //如果没有发生数据交换,直接退出
IfChanged = false; //恢复默认值
Console.WriteLine("第" + j.ToString() + "次排序的结果");
for (int m = 0; m < list.Length; m++)
{
Console.Write("{0} ", list[m]);
}
Console.WriteLine();
}
}
4.//希尔排序
希尔排序(缩小增量法)
属于插入类排序,是将整个无序列分割成若干小的子序列分别进行插入排序
排序过程:先取一个正整数d1<n,把所有序号相隔d1的数组元素放一组,组内进行直接插入排序;然后取d2<d1,重复上述分组和排序操作;直至di=1,即所有记录放进一个组中排序为止
初始:d=5
49 38 65 97 76 13 27 49* 55 04
49 13
|-------------------|
38 27
|-------------------|
65 49*
|-------------------|
97 55
|-------------------|
76 04
|-------------------|
一趟结果
13 27 49* 55 04 49 38 65 97 76
d=3
13 27 49* 55 04 49 38 65 97 76
13 55 38 76
|------------|------------|------------|
27 04 65
|------------|------------|
49* 49 97
|------------|------------|
二趟结果
13 04 49* 38 27 49 55 65 97 76
d=1
13 04 49* 38 27 49 55 65 97 76
|----|----|----|----|----|----|----|----|----|
三趟结果
04 13 27 38 49* 49 55 65 76 97
--------------------------------------------------------------------------------------------
例如对503,17,512,908,170,897,275,653,462,154,509,612,677,765,703,94排序的C语言算法
================================================
功能:希尔排序
输入:数组名称(也就是数组首地址)、数组中元素个数
================================================
*/
/*
====================================================
算法思想简单描述:
在直接插入排序算法中,每次插入一个数,使有序序列只增加1个节点,
并且对插入下一个数没有提供任何帮助。如果比较相隔较远距离(称为
增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除
多个元素交换。D.L.shell于1959年在以他名字命名的排序算法中实现
了这一思想。算法先将要排序的一组数按某个增量d分成若干组,每组中
记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量
对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成
一组,排序完成。
下面的函数是一个希尔排序算法的一个实现,初次取序列的一半为增量,
以后每次减半,直到增量为1。
希尔排序是不稳定的。
public void ShellSort(int[] list)
{
int inc;
for (inc = 1; inc <= list.Length / 9; inc = 3 * inc + 1) ;
for (; inc > 0; inc /= 3)
{
for (int i = inc + 1; i <= list.Length; i += inc)
{
int t = list[i - 1];
int j = i;
while ((j > inc) && (list[j - inc - 1] > t))
{
list[j - 1] = list[j - inc - 1];
j -= inc;
}
list[j - 1] = t;
}
}
}
5.希尔(插入)排序 c#代码
基本思想
希尔排序基本思想: 先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为dl的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。 该方法实质上是一种分组插入方法。 给定实例的shell排序的排序过程 假设待排序文件有10个记录,其关键字分别是: 49,38,65,97,76,13,27,49,55,04。增量序列的取值依次为: 5,3,1
① 最后一个增量必须为1;
解读:
希尔排序算法引入了一个增量,该增量把原来的序列分割成多个序列,先在各个序列内进行插入排序,使整个序列变的“基本有序”。增量可以是多个,最后一个必须是1.本文的例子增量是5,3,1
当增量是5的时候,{【1】,【6】},{【2】,【7】}……是一组,总共5组。
他们先进行第一个希尔排序
然后增量为3的时候,{【1】,【4】,【7】,【9】},{【2】,【5】,【8】},{【3】,【6】,【9】}是一组。
继续进行希尔排序。
最后增量是1.整个序列是一组。
(1)c#代码
/// <summary>
/// 希尔(插入)排序
/// </summary>
/// <param name="array"></param>
/// <param name="increments">增量集合</param>
static void ShellOrder(ref int[] array,int[] increments)
{
for(int n = 0;n < increments.Length;n++)
{
ShellInsert(ref array, increments[n]);
}
}
static void ShellInsert(ref int[] array, int dk)
{
for (int i = 1 + dk; i < array.Length; ++i)
{
if (array[i] < array[i - dk])//如果小于,【i】赋值到哨兵中。
{
array[0] = array[i];
int j = 0;
for (j = i - dk; j > 0 && array[0] < array[j] ; j -= dk)//记录后移,插入排序的基本原理,空出正确的位置
{
array[j + dk] = array[j];
}
array[j + dk] = array[0];
}
}
}
//调用
int[] array = {0,49,38,65,97,76,13,27,49 };
int[] increments ={ 5,3,1};
ShellOrder(ref array, increments);
for (int n = 0; n < array.Length; n++)
{
Console.Write(array[n].ToString() + ",");
}
浙公网安备 33010602011771号