文章目录
排序——数据结构
排序
假设含有n个记录的序列为{r1,r2,……,rn},其相应的关键字分别为{k1,k2,……,kn},需要确定一种排列,使其相应的关键字满足非递增或非递减关系,即使得序列成为一个按关键字有序的序列,这样的操作就称为排序。
排序的稳定性
假设ki=kj (1<=i<=n,1<=j<=n,i≠j) ,且在排序前的序列中ri领先于rj(即i<j)。如果排序后ri仍领先于rj,则称所用的排序方法是稳定的;反之,若可能使得排序后的序列中rj领先ri,则称所用的排序方法是不稳定的。
直接插入排序
直接插入排序的基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表。
直接插入的实现
//直接插入
void InsertSort(int* a, int n)
{
//多趟排序
//控制end的位置从0走到n-2
for (int i = 0; i < n - 1; i++)
{
//单趟排序
//在[0,end]区间中插入tmp,依旧有序
int end = i;
int tmp = a[end + 1];
while (end >= 0)
{
if (a[end] > tmp)
{
a[end + 1] = a[end];
end--;
}
else
{
break;
}
}
a[end + 1] = tmp;
}
}
直接插入的特点
- 元素集合越接近有序,直接插入排序算法的时间效率越高
- 时间复杂度:O(N^2)
- 空间复杂度:O(1)
- 稳定性:稳定
希尔排序
先选定一个整数gap,把待排序文件中所有记录分组,所有距离为gap的记录分在同一组内,并对每一组内的记录进行排序。然后,重复上述分组和排序的工作。当到达gap=1时,所有记录在统一组内排好序 。
希尔排序的实现
//希尔排序
void ShellSort(int* a, int n)
{
//gap>1时,为预排序,接近有序
//gap=1时,为直接插入排序
int gap = n;
while (gap > 1)
{
gap = gap / 3 + 1;
//3个间隔为gap的组同时交叉排序
for (int i = 0; i < n - gap; i++)
{
//间隔为gap的预排序
int end = i;
int tmp = a[end + gap];
while (end >= 0)
{
if (a[end] > tmp)
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tmp;
}
}
}
希尔排序的特点
- 希尔排序是对直接插入排序的优化。
- 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。
- 希尔排序的时间复杂度不好计算,需要进行推导,推导出来平均时间复杂度: O(N1.3—N2)
- 稳定性:不稳定
简单选择排序
每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
简单选择的实现
void Swap(int* a, int* b)
{
int* tmp = *a;
*a = *b;
*b = tmp;
}
//直接选择排序
//一次选择两个数,最小的放前边,最大的放后边
void SelectSort(int* a, int n)
{
int begin = 0, end = n - 1;
while (begin < end)
{
//[begin,end]区间选出一个最小的一个最大的数的下标
int min = begin, max = end;
for (int i = begin; i <= end; i