数据结构和算法——堆排序(选择排序、思路图解、代码、时间复杂度、堆排序及代码)

简介: 数据结构和算法——堆排序(选择排序、思路图解、代码、时间复杂度、堆排序及代码)

选择排序

思路图解

代码(C语言)

void Selection_Sort(ElementType A[], int N)
{
    for(i = 0; i < N; i++)
    {
        MinPosition = ScanForMin(A,i,N-1);
        //从A[i]到A[N-1]中找最小元,并将其位置赋给MinPosition
        Swap( A[i], A[MinPosition] );
        //将未排序部分的最小元换到有序部分的最后位置
    }
}

时间复杂度

要提高时间效率,关键在于如何快速找到最小元,所以引入堆排序:

堆排序

算法1

先看第一种算法:

void Heap_Sort(ElementType A[], int N)
{
    BuildHeap( A );    /*  o(N)  */
    for( i = 0; i < N; i++)
        TmpA[ i ] = DeleteMin( A );    /*  O(logN)  */
    for( i = 0; i < N; i++)      /*   O(N)   */
        A[ i ] = TmpA[ i ];  
}

它的思路是:

先将序列A建成堆,然后重复地从堆中提取最小元素,并将其存储在临时数组中,实现了堆排序算法。最后,它将排序后的元素复制回原始数组A。

时间复杂度:

空间上,需要额外O(N)的内存占用,并且复制元素需要时间。

(在内存足够的情况下,一般没有问题;但如果在固定内存中使用这种算法的堆排序,就会出现无法完成排序的情况;例如:2GB满内存的情况下,要对该序列进行排序,那么实际就需要4GB的内存来进行堆排序。)

所以这种算法是不太好的。

算法2

void Heap_Sort(ElementType A[], int N)
{
    for(i = N/2 - 1; i >= 0; i--)
        PercDown(A ,i ,N);
    for(i = N - 1; i > 0; i--)
    {
        Swap(&A[0], &A[i] );
        PercDown(A ,0 ,i);
    }
}

算法2的思路是:

定理:

堆排序处理N个不同元素的随机排序的平均比较次数是

虽然堆排序给出最佳平均时间复杂度,但实际效果不如用Sedgewick增量序列的希尔排序。

 

堆排序代码

void Swap( ElementType *a, ElementType *b )
{
     ElementType t = *a; *a = *b; *b = t;
}
 
void PercDown( ElementType A[], int p, int N )
{ 
  /* 将N个元素的数组中以A[p]为根的子堆调整为最大堆 */
    int Parent, Child;
    ElementType X;
 
    X = A[p]; /* 取出根结点存放的值 */
    for( Parent=p; (Parent*2+1)<N; Parent=Child ) {
        Child = Parent * 2 + 1;
        if( (Child!=N-1) && (A[Child]<A[Child+1]) )
            Child++;  /* Child指向左右子结点的较大者 */
        if( X >= A[Child] ) break; /* 找到了合适位置 */
        else  /* 下滤X */
            A[Parent] = A[Child];
    }
    A[Parent] = X;
}
 
void HeapSort( ElementType A[], int N ) 
{ /* 堆排序 */
     int i;
      
     for ( i=N/2-1; i>=0; i-- )/* 建立最大堆 */
         PercDown( A, i, N );
     
     for ( i=N-1; i>0; i-- ) {
         /* 删除最大堆顶 */
         Swap( &A[0], &A[i] ); 
         PercDown( A, 0, i );
     }
}

end



目录
打赏
0
0
0
0
74
分享
相关文章
java实现队列数据结构代码详解
本文详细解析了Java中队列数据结构的实现,包括队列的基本概念、应用场景及代码实现。队列是一种遵循“先进先出”原则的线性结构,支持在队尾插入和队头删除操作。文章介绍了顺序队列与链式队列,并重点分析了循环队列的实现方式以解决溢出问题。通过具体代码示例(如`enqueue`入队和`dequeue`出队),展示了队列的操作逻辑,帮助读者深入理解其工作机制。
|
1月前
|
算法系列之数据结构-二叉树
树是一种重要的非线性数据结构,广泛应用于各种算法和应用中。本文介绍了树的基本概念、常见类型(如二叉树、满二叉树、完全二叉树、平衡二叉树、B树等)及其在Java中的实现。通过递归方法实现了二叉树的前序、中序、后序和层次遍历,并展示了具体的代码示例和运行结果。掌握树结构有助于提高编程能力,优化算法设计。
58 9
 算法系列之数据结构-二叉树
|
1月前
|
算法系列之数据结构-Huffman树
Huffman树(哈夫曼树)又称最优二叉树,是一种带权路径长度最短的二叉树,常用于信息传输、数据压缩等方面。它的构造基于字符出现的频率,通过将频率较低的字符组合在一起,最终形成一棵树。在Huffman树中,每个叶节点代表一个字符,而每个字符的编码则是从根节点到叶节点的路径所对应的二进制序列。
66 3
 算法系列之数据结构-Huffman树
算法系列之排序算法-堆排序
堆排序(Heap Sort)是一种基于堆数据结构的比较排序算法。它的时间复杂度为 $O(nlogn)$,并且是一种原地排序算法(即不需要额外的存储空间)。堆排序的核心思想是利用堆的性质来维护一个最大堆或最小堆,然后逐步将堆顶元素(最大值或最小值)取出,放到数组的末尾,最终得到一个有序的数组。
48 8
算法系列之排序算法-堆排序
|
1月前
|
算法系列之数据结构-二叉搜索树
二叉查找树(Binary Search Tree,简称BST)是一种常用的数据结构,它能够高效地进行查找、插入和删除操作。二叉查找树的特点是,对于树中的每个节点,其左子树中的所有节点都小于该节点,而右子树中的所有节点都大于该节点。
84 22
C 408—《数据结构》算法题基础篇—链表(下)
408考研——《数据结构》算法题基础篇之链表(下)。
112 29
|
5月前
|
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
575 9
|
5月前
|
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
144 58
|
3月前
|
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
240 77
|
2月前
|
STL——栈和队列和优先队列
通过以上对栈、队列和优先队列的详细解释和示例,希望能帮助读者更好地理解和应用这些重要的数据结构。
37 11