您的位置:首页 > 其它

排序算法--------插入排序和选择排序

2018-03-11 16:31 441 查看

1. 插入排序

直接插入

将待排序元素插入到前面已经有序的数组中,直至将待排序元素全部插完(过程如下图)

具体步骤:

(1)比较待插入元素(key)和有序序列的最后一个元素(a[end]),如果 key>=a[end],直接插入,反之交换key和a[end]

(2)如果key< a[end],继续在有序区间里寻找小于key的元素(tmp),将key插入到tmp的后面



希尔排序

是直接插入排序的优化;当待排序元素较多时,直接插入的效率反而会变得很低,越接近有序的序列使用直接插入排序时,效率越高,故在进行插入排序之前进行预排序,使其待排序序列接近有序(如下图)



二者算法分析

稳定性

直接插入排序是稳定算法,排序码的相对位置不会改变

希尔排序是不稳定算法,在进行预排序时,排序码的相对位置可能发生改变

时间复杂度

直接插入排序

最优情况:待排序序列越接近有序,算法效率越高,时间复杂度为O(N)

最差情况:当待排序序列很大,并且不是很接近有序,算法效率大大降低,时间复杂度为O(n2n2)

希尔排序

希尔排序是直接插入排序的优化,但当待排序数列很大时,预排序过程效率会降低许多,时间复杂度为O(n2n2)

空间复杂度

空间复杂度都为O(1),在进行排序时,会创建临时常数个临时变量用于控制下标

代码:

/*****************直接插入排序************/
void InsertSort(DataType* a, size_t n)
{
assert(a);

int end;
for (size_t i = 0; i < n - 1; ++i)
{
end = i;
while (end >= 0 && a[end]>a[end + 1])
{
//待插入序列大于有序序列的最后一个
Swap(&a[end], &a[end + 1]);
--end;
}
}
}

/**********希尔排序******************/
void ShellSort(DataType* a, size_t n)
{
assert(a);

//先进行预排序
int gap = n / 3 + 1;//进行预排序时的跨度

while (gap > 1)
{
for (size_t i = 0; i < n - gap; ++i)
{
size_t end = i;

while (end >= 0 && a[end] >= a[end+gap])
{
Swap(&a[end], &a[end + gap]);
end -= gap;
}
}
gap = gap / 3 + 1;
}

InsertSort(a, n);
}


2.选择排序

选择排序

4000

每遍历一次待排序序列,选出最大和最小的数,分别放在左边和右边的相应位置上,直到全部选出为止(如下图)



堆排序

将待排序序列建堆,每次将堆顶数据与堆尾数据进行交换,在进行堆的调整(部分过程图)



二者算法分析

稳定性

直接选择排序是不稳定算法,排序码的相对位置会发生改变

堆排序是不稳定算法,在进行建堆和调整堆时,排序码的相对位置发生改变

时间复杂度

直接选择排序

时间复杂度为O(N*N)

移动次数最好情况为0次

堆排序

建堆的时间复杂度为O(N*logN)

建堆后,每次排序时间复杂度为O(logN)

综上,堆排序的时间复杂度为O(N*logN)

空间复杂度

空间复杂度都为O(1),在进行排序时,会创建常数个临时变量用于控置下标

需要占用一个临时空间,在交换数值时使用。

代码

/*******************选择排序*************/
void SelectSort(DataType* a, size_t n)
{
assert(a);

size_t left = 0;
size_t right = n - 1;

while (left < right)
{
//排序结束条件,两边错过
size_t min = left;
size_t max = left;

for (size_t i = left; i <=right ; ++i)
{
//遍历数组,选出最小的数和最大的数
if (a[min] > a[i])
{
//放到最左边
min = i;
}

if (a[max] < a[i])
{
//放到最右边
max = i;
}
}

//进行交换
Swap(&a[left], &a[min]);

//当最大的数在最左边,需将max的位置置为最小值
if (max == left)
{
max = min;
}
Swap(&a[right], &a[max]);

left++, right--;
}
}

/*****************堆排序****************/
void  HeapSort(DataType* a1, size_t n)
{
assert(a);

//建堆,升序建大堆,降序建小堆
int i = (n - 2) >> 1;
for (; i >= 0; --i)
{
AdjustDown(a, n, i);
}

for (int j = n-1;j>0; --j)
{
Swap(&a[j], &a[0]);
AdjustDown(a, j, 0);
}
}

//向下调整
void AdjustDown(DataType* a1, size_t n, size_t parent)
{
size_t child = parent * 2 + 1;

while (child < n)
{
//选出左右孩子当中较大的
if ((child + 1) < n && a[child] < a[child + 1])
{
++child;
}

if (a[parent] < a[child])
{
Swap(&a[parent], &a[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息