有了前两篇文章的基础(冒泡排序、插入排序的传送门),到这里可以加快速度,就将这三个排序算法放在了一起写了,以免一篇文章字数过少。
1.选择排序
在计算机科学中,选择排序是一种排序算法,特别是就地 比较排序。它具有O(n^2)时间复杂度,使其在大型列表上效率低,并且通常比类似的插入排序更差。选择排序因其简单性而着称,并且在某些情况下具有优于更复杂算法的性能优势,特别是在辅助存储器有限的情况下。
该算法将输入列表分为两部分:已经排序的项目子列表,在列表的前面(左侧)从左到右构建,以及剩余要排序的项目的子列表占用其余部分。名单。最初,排序的子列表为空,未排序的子列表是整个输入列表。该算法通过查找未排序子列表中的最小(或最大,取决于排序顺序)元素,与最左边的未排序元素(将其按排序顺序)交换(交换),并将子列表边界向右移动一个元素来继续。
具体实现代码如下:
void Bubble::goChoice()
{
for (int i = 0;i < length; i++) { //先进行整体循环遍历
int index = i; //当前比较的位子
for (int j = i+1;j < length; j++) {
if(data[index] > data[j]){ //在余下的数找到其最小的数
index = j;
bubbleSignal(j);
QThread::msleep(static_cast<unsigned int>(mDelay));
}
}
if(index == i) //没有找到,即表示当前数是余下数的最小数
continue;
else { //找到,即将当前位子的数与找到的数进行交换
int temp = data[index];
data[index] = data[i];
data[i] = temp;
}
bubbleSignal(i);
QThread::msleep(static_cast<unsigned int>(mDelay));
}
for(int i = 0; i < length;i++){
bubbleSignal(i);
QThread::msleep(static_cast<unsigned int>(mDelay));
}
}
运行结果
2.堆排序
Wiki介绍:
在计算机科学中,heapsort是一种基于比较的 排序算法。Heapsort可以被认为是一种改进的选择排序:像该算法一样,它将输入分为排序区域和未排序区域,并通过提取最大元素并将其移动到排序区域来迭代缩小未排序区域。改进包括使用堆数据结构而不是线性时间搜索来找到最大值。[1]
尽管在大多数机器上实际上比实施良好的快速排序有些慢,但它具有更有利的最坏情况O(n log n)运行时间的优点。Heapsort是一种就地算法,但它不是一个稳定的类型。
基本思想是:
将待排序的序列构造成一个大顶堆。此时,整个序列的最大值就是堆顶的根结点。将它与堆数组的末尾元素进行交换,此时末尾元素就是最大值,然后将剩余的前n-1个序列重新构造成一个堆,这样就会得到n个元素中的次大值。如此反复执行,便能得到一个重小到大的有序序列。
void Bubble::goHeap()
{
// 初始化堆
// length / 2 - 1是二叉树中最后一个非叶子结点的序号
for (int i = length / 2 -1; i >= 0; i--)
{
heapAdjust(i,length);
bubbleSignal(i);
QThread::msleep(static_cast<unsigned int>(mDelay));
}
// 交换堆顶元素和最后一个元素
for (int i = length-1; i >= 0; i--)
{
int temp;
temp = data[i];
data[i] = data[0];
data[0] = temp;
heapAdjust(0,i);
bubbleSignal(i);
QThread::msleep(static_cast<unsigned int>(mDelay));
}
for(int i = 0; i < length;i++){
bubbleSignal(i);
QThread::msleep(static_cast<unsigned int>(mDelay));
}
}
//构建一个大顶堆
void Bubble::heapAdjust(int i, int len)
{
int temp = data[i];
for(int j = 2*i+1;j <len; j=j*2+1){
if(j < len-1 && data[j] < data[j + 1]){
++j;
}
if(temp >= data[j])
break;
data[i] = data[j];
i = j;
bubbleSignal(i);
QThread::msleep(static_cast<unsigned int>(mDelay));
}
data[i] = temp;
}
运行结果
3.希尔排序
引用Wiki的介绍:
Shellsort,也称为Shell sort或Shell的方法,是一种就地比较排序。它可以看作是通过交换排序(冒泡排序)或通过插入排序(插入排序)的概括。该方法首先对彼此远离的元素对进行排序,然后逐步减小要比较的元素之间的差距。从相距很远的元素开始,它可以比一个简单的最近邻交换更快地将一些不合适的元素移动到位。唐纳德·壳牌于1959年发布了这种类型的第一个版本。Shellsort的运行时间在很大程度上取决于它使用的间隙序列。对于许多实际的变体,确定它们的时间复杂度仍然是一个未解决的问题。
基本思想:
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量 =1( < …<d2<d1),即所有记录放在同一组中进行直接插入排序为止。实质上是一种进行多次分组插入排序的过程。
void Bubble::goShell()
{
int increasement = length;
int i, j, k;
do
{
// 确定分组的增量
increasement = increasement / 3 + 1;
for (i = 0; i < increasement; i++)
{
for (j = i + increasement; j < length; j += increasement)
{//这里跟插入排序的思想一样,只是增量不同
if (data[j] < data[j - increasement])
{
int temp = data[j];
for (k = j - increasement; k >= 0 && temp < data[k]; k -= increasement)
{
data[k + increasement] = data[k];
bubbleSignal(k);
QThread::msleep(static_cast<unsigned int>(mDelay));
}
data[k + increasement] = temp;
}
}
}
} while (increasement > 1);
for(int i = 0; i < length;i++){
bubbleSignal(i);
QThread::msleep(static_cast<unsigned int>(mDelay));
}
}
运行结果
4.总结
本文没有详细介绍各个排序算法的具体实现细节和逻辑,是因为觉得个人并不能以足够的通俗易懂语言讲解出来,以免产生误解,在此给大家推荐一本个人觉得非常好的书--《大话数据结构》。书里面讲解的十分详细和生动,大家不妨去看看。