插入排序
插入排序的基本思想是:每步将一个待排序的记录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。
例如:
桌上总共有十张打乱顺序的扑克牌,我开始抓牌,每次只抓一张然后让扑克牌在手里排成从小到大的顺序.带入上边的基础思想中,我桌上的排就是待排序的记录,我手里的牌是已经排好顺序的,将刚刚抓到手的牌按照从小到大的规则插入到相对应的位置直到桌上的牌抓完为止,这样的排序过程就是插入排序.
整个过程中我有很多细节值得去推敲,比如:刚刚抓到的牌跟手里已经排好顺序的牌怎样去比较,从小的一端开始,还是从大的一端开始,由多种的比较过程和方法共同组成了插入排序.
第一张:
第二张:
第三张:
第四张
第五张:
第六张:
第七张:
第八张:
第九张:
第十张:
效率:如果目标是把n个元素的序列升序排列,那么采用插入排序存在最好情况和最坏情况。最好情况就是,序列已经是升序排列了,在这种情况下,需要进行的比较操作需(n-1)次即可。最坏情况就是,序列是降序排列,那么此时需要进行的比较共有n(n-1)/2次。插入排序的赋值操作是比较操作的次数加上 (n-1)次。平均来说插入排序算法的时间复杂度为O(n^2)
代码实现:
//定义数组
int[] arr = new int[]{5, 8, 6, 1, 3, 4, 7, 2, 0,9};
//第一个数为有序,其他数位无序
for (int i = 1; i < arr.Length; i++)
{
int temp = arr[i];
//依次和有序数做比较
for (int j = i;j>0; j--)
{
if (arr[j] < arr[j - 1])
{
arr[j] = arr[j - 1];
arr[j - 1] = temp;
}
}
}
//遍历数组
for (int i = 0; i < arr.Length; i++)
{
Console.WriteLine(arr[i]);
}
Console.Read();
希尔排序
希尔排序(Shell's Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
根据以上的概念说明现有14个数的数组如下:
1, 5, 3, 6, 10, 55, 9, 2, 87, 12, 34, 75, 33, 47
首先将14个数分成7组步长为7,相同背景颜色的为一组
同一组排序之后的顺序
d->7
然后按照第一次排序的顺序重新将14个数分成3组步长为3,相同背景颜色的为一组
同一组排序之后的顺序
d->3
最后按照步长为1来进行排序,因为步长为1就只有一组,没有分组的说法了.所以排序后的结果就是最终结果
d->1
1 , 2 , 3 , 5 , 6 , 9 , 10, 12, 33, 34, 47, 55, 75, 87,
效率:
最坏情况时间复杂度为:O(n^1.5),平均时间复杂度为O(nlogn)。
代码实现:
//模拟数据
int[] iArrary = new int[] { 1, 5, 3, 6, 10, 55, 9, 2, 87, 12, 34, 75, 33, 47 };
ShellSorter sh = new ShellSorter();
sh.Sort(iArrary);
for (int m = 0; m <= 13; m++)
{
Console.WriteLine("{0}", iArrary[m]);
}
Console.ReadKey();
}
//希尔排序类
class ShellSorter
{
public void Sort(int[] list)
{
int _d = list.Length;
int _len = list.Length;
for (_d = _d / 2; _d > 0;)
{
if (_d % 2 == 0) _d++;
//按d分组
for (int i = 0; i < _d; i++)
{
//每组执行直接插入排序算法
for (int j = i + _d; j < _len; j += _d)
{
if (j < _len)
{
if (list[j] < list[j - _d])//后面小于前面
{
int temp = list[j];
int k = 0;
for (k = j - _d; k >= i && temp < list[k]; k -= _d)//比它大的元素后移动
{
list[k + _d] = list[k];
}
list[k + _d] = temp;//插入最后比它小的后面
}
}
}
}
Console.WriteLine("第一次d->" + _d);
for (int i = 0; i < _len; i++)
{
Console.Write(string.Format("{0},", list[i]));
}
Console.WriteLine("");
_d = _d / 2;
}
}
}