一:插入排序
在一组无序的数组中,假设第一个有序,每一次数组中剩余的元素与第一个比较,然后逐个插入到一个有序的序列中,直到这个数组所有的数字有序为止;
二:直接插入算法
算法思路:
1:我们先假设第一个有序的数字下标为end,
2:下一个要插入的数字(tmp)继续构成有序就直接插入,此时end向后挪一位,
3:继续插入元素,如果下一个插入的数字和第一个不成构成有序,先与前一个元素交换,然后把end的下标–,直到所有的元素都有序结束。
实现
template<class T>
struct Less
{
bool operator() (const T &a, const T &b)
{
return a < b;
}
};
template<class T>
struct Greater
{
bool operator() (const T &a, const T &b)
{
return a >b;
}
};
template<class T,class Compare>
void InsertSort(T * _a, size_t n)
{
for (size_t i = 0; i< n - 1; i++)
{
int end = i;
int tmp = _a[end + 1];
while (end >= 0)
{
if (Compare()(_a[end],tmp))
{
_a[end + 1] = _a[end];
}
else
{
break;
}
end -= 1;
}
_a[end + 1] = tmp;
}
}
template<class T>
void PrintSort(T*a, size_t n)
{
for (size_t i = 0; i < n; ++i)
{
cout << a[i] << " ";
}
cout << endl;
}
void TestSelect()
{
int a[] = { 1, 5, 2, 4, 3, 7, 9, 8, 0, 6 };
int n = sizeof (a) / sizeof(a[0]);
InsertSort<int, Greater<int>>(a, n);
PrintSort(a, n);
}
分析:
直接插入排序最坏的时间复杂度O(N^2),也就是将一个有序的数组逆序,最好的时间复杂度O(N),就是有序;那么如何让插入算法更加高效呢?
三:希尔排序
希尔排序又称缩小增量排序,我们可以看成是直接插入排序的改进版本;
,当数字的基数很大时,而且都接近无序,如果用插入算法一个个比较后再插入,时间很高,我们可以借助分制的思想,我一个大的无序数组,分成若干个小序列列,再进行插入排序这样就会很快;
算法思路:
1:首先进行预排序,将大的元素尽快到后面,小的元素尽快到前面
2:然后取间距gap
template<class T>
struct Less
{
bool operator() (const T &a, const T &b)
{
return a < b;
}
};
template<class T>
struct Greater
{
bool operator() (const T &a, const T &b)
{
return a >b;
}
};
template<class T>
void PrintSort(T*a, size_t n)
{
for (size_t i = 0; i < n; ++i)
{
cout << a[i] << " ";
}
cout << endl;
}
template<class T,class Compare>
void ShellSort(T*_a, size_t n)
{
int gap =n;
while (gap > 1)
{
gap =gap / 3 +1;
for (size_t i = 0; i < n-gap; ++i)
{
int end = i;
int tmp = _a[end + gap];
while (end >= 0)
{
if (Compare()(_a[end], tmp))
{
_a[end+gap] = _a[end];
}
else
{
break;
}
end -= gap;
}
_a[end + gap] = tmp;
}
}
}
void TestShellSort()
{
int a[] = { 1, 5, 2, 4, 3, 7, 9, 8, 0, 6 };
int n = sizeof(a) / sizeof(a[0]);
ShellSort<int, Less<int>>(a, n);
PrintSort(a, n);
}
四:总结:
1:直接插入排序:
适合一个有序的序列。而且范围不是很大,快速高效,时间复杂度最快O(n)
缺陷:
当序列的范围很大时,或者逆序时时间复杂度O(n^2)
2:希尔排序:
解决序列的范围很大时的排序;
分制思想:将大的序列,根据距离分成若干个小的序列;
每个小的序列进行插入排序,当距离为1时,进行直接插入排序。