堆排序【代码】

思路参考《算法导论》P84

堆排序中用到的最重要的就是堆这种数据结构,也正是因为这种数据结构能把时间复杂度控制在O(n * lgn)

heapsort算法主要依赖于两个函数

MAX_HEAPIFY(int *A,int i,int len)

用于维护最大堆,时间复杂度为O(lgn),注意书上描述这个函数的算法只用了两个形参,而由于C++无法通过指针获取数组的大小,所以我额外添加了一个参数作为数组的大小

BUILD_MAX_HEAP(int *A,int len)

从无序的输入数据数组中构造一个最大堆,时间复杂度为O(n),这里同样添加了一个参数

如果用其他语言比如Java实现,只需把数组名作为参数穿进来即可,Java支持数组拷贝,支持通过数组名获取数组大小,比这里简单一点

排序算法的详细过程就不描述了,书上讲的挺清楚的

----------------------------------------------------------代码-------------------------------------------------------

  1 // Heapsort.cpp: 定义控制台应用程序的入口点。
  2 //
  3
  4
  5 #include "stdafx.h"
  6 #include <iostream>
  7
  8 using namespace std;
  9
 10 int PARENT(int i)
 11 {
 12     return (i - 1) / 2;
 13 }
 14
 15 int LEFT(int i)
 16 {
 17     return 2 * i + 1;
 18 }
 19
 20 int RIGHT(int i)
 21 {
 22     return 2 * i + 2;
 23 }
 24 //维护最大堆,时间复杂度为O(lgn)
 25 int MAX_HEAPIFY(int *A,int i,int len)
 26 {
 27     int l, r, largest;//l为左孩子的下标,r为右孩子的下标,largest为三者中最大数的下标
 28     int temp;
 29     l = LEFT(i);
 30     r = RIGHT(i);
 31     if (l < len && A[l] > A[i])
 32         largest = l;
 33     else
 34         largest = i;
 35
 36     if (r < len && A[r] > A[largest])
 37         largest = r;
 38
 39     if (largest != i)
 40     {
 41         temp = A[i];
 42         A[i] = A[largest];
 43         A[largest] = temp;
 44         MAX_HEAPIFY(A, largest, len);
 45     }
 46     else
 47     {
 48         if (l >= len && r >= len)//到达了叶节点,停止递归
 49         {
 50             return 0;
 51         }
 52         MAX_HEAPIFY(A, l, len);
 53         MAX_HEAPIFY(A, r, len);
 54     }
 55 }
 56
 57 //从无序的输入数据数组中构造一个最大堆,时间复杂度为O(n)
 58 int BUILD_MAX_HEAP(int *A,int len)
 59 {
 60     int start = PARENT(len);
 61     for (int i = start; i >= 0; i--)
 62     {
 63         MAX_HEAPIFY(A, i, len);
 64     }
 65     return 0;
 66 }
 67
 68 int HEAPSORT(int *A,int len)
 69 {
 70     int length = len;
 71     int *res = new int[len]{0};//记录排完序后的结果
 72     int ptr = len - 1;
 73     BUILD_MAX_HEAP(A, len);
 74
 75     for (int i = 0; i < length; i++)
 76         cout << A[i] << ends;
 77     cout << endl << endl;
 78
 79     for (int i = length; i >= 1; i--)
 80     {
 81         res[ptr--] = A[0];
 82         A[0] = A[len-1];
 83         len--;
 84         int *A_temp = new int[len];
 85         for (int i = 0; i < len; i++)//把删掉最后一个元素后的数组A复制到A_temp中
 86         {
 87             A_temp[i] = A[i];
 88         }
 89         MAX_HEAPIFY(A_temp, 0, len);//对A_temp重新维持为最大堆
 90         for (int i = 0; i < len; i++)//把A_temp的值复制给A
 91         {
 92             A[i] = A_temp[i];
 93         }
 94
 95         for (int i = 0; i < len; i++)
 96             cout << A[i] << ends;
 97         cout << endl;
 98         delete A_temp;
 99     }
100
101     cout << "排序后的数组为(升序):" << endl;
102     for (int i = 0; i < length; i++)
103         cout << res[i] << ends;
104     cout << endl;
105     return 0;
106 }
107
108 int main()
109 {
110     int A[] = {16,4,10,14,7,9,3,2,8,1};
111     cout << "排序前的数组为:" << endl;
112     for (auto c : A)
113         cout << c << ends;
114     cout << endl;
115     /*BUILD_MAX_HEAP(A,10);
116     for (auto c : A)
117         cout << c << ends;
118     cout << endl;*/
119     HEAPSORT(A,10);
120     return 0;
121 }

运行结果:

原文地址:https://www.cnblogs.com/journal-of-xjx/p/8279640.html

时间: 2024-11-02 16:44:26

堆排序【代码】的相关文章

堆排序+代码实现

堆排序 堆,heap,是二叉树的一种.小根堆有这样的性质--任意一个结点的值比它的左右孩子都要小. 排序思想 将待排元素看作是完全二叉树,物理上用一维数组存储. 实现堆排序需要解决两个问题: 1.如何将杂乱的完全二叉树初始化为一个堆? 答:从最后一个非叶结点起,将该节点当做根,自上而下进行调整,使之成为一个堆.然后依次对倒数第二个.倒数第三个.直至正数第一个结点进行此操作. 2.输出堆顶元素后,如何将余下的元素调整为一个堆? 答:将最后一个结点放在原根结点位置上,以它为根进行上述的调整. 复杂度

java 堆排序代码(最小堆)

package com.juxuny.heap; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.List; /** * Created by Juxuny on 2015/2/10. */ public class Heap { private int MAX = 2 << 20; private Node[] arr; private int size = 0; public Heap

【算法导论】第六章、堆排序

基本过程: 1.保持最大堆的性质:假设两个子堆都满足,只需要根节点依次换下去,复杂度O(lg n) 2.初始化堆:后半段都是叶子,在前半段从后往前,依次执行上述最大堆性质的操作,名义复杂度是O(n lg n),但是有更精确的计算, 在高度为h的节点为O(h), 因此为 n\sigma (h / 2^h),其复杂度为O(n).(思想是高层复杂度才高,指数衰减,而复杂度增长是lg级别,因此被dominate掉了) 堆排序算法:先建最大堆,每次把顶上的位置与合适的位置互换,然后执行过程1, 共执行n次

十大基础实用算法之快速排序和堆排序

快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来. 快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists). 算法步骤: 1 从数列中挑出一个元素,称为 "基准"(pi

排序算法——堆排序

堆排序 ①了解二叉堆的定义 ②一般用数组表示堆 注意逻辑存储结构和实际存储结构 ③i节点的 父节点(i-1)/2 子节点 左2*i+1 右2*i+2 ④注意每种操作的思想 ⑤一般数组要堆化操作后再进行堆排序 代码实现 /*本栗子是最小堆*//*从第i个节开始调整*/ void MinHeapDown(int a[],int i,int n) { int j=0,temp=0; temp = a[i]; j=2*i+1;/*i节点的左孩子*/ while(j < n) { if(j+1<n &a

选择排序:堆排序

堆排序(Heap Sort):使用堆这种数据结构来实现排序. 先看下堆的定义: 最小堆(Min-Heap)是关键码序列{k0,k1,-,kn-1},它具有如下特性: ki<=k2i+1, ki<=k2i+2(i=0,1,-) 简单讲:孩子的关键码值大于双亲的. 同理可得,最大堆(Max-Heap)的定义: ki>=k2i+1, ki>=k2i+2(i=0,1,-) 同样的:对于最大堆,双亲的关键码值大于两个孩子的(如果有孩子). 堆的特点: 堆是一种树形结构,而且是一种特殊的完全二

数据结构之堆排序

堆排序,是数据结构中重要的排序方法,可以很快帮你找到最大值.在实际应用中,如 最大优先级队列是大顶推的应用,可以很快找到优先级最高的队列. 1.堆概念 堆的定义如下,n个元素的序列{k1,k2,...kn},当且仅当满足如下关系: ki>=k2i               或者         ki<=k2i ki>=k2i+1                          ki<=k2i+1 分别对应大顶堆和小顶堆. 堆可以看作一个完全二叉树,所有非终端点都大于或都小于左右

夯实基础——堆排序

堆结构:任意的一个父节点大于其子节点. 逻辑结构:二叉树 物理结构:数组 如果从角标0开始 父节点左孩子节点:2*i+1 父节点右孩子节点:2*i+2 最后一个非叶节点:(n-1)/2 如果从角标1开始 父节点左孩子节点:2*i 父节点右孩子节点:2*i+1 最后一个非叶节点:n/2 堆排序分析: 最优时间复杂度:O(nlog2n) 最坏时间复杂度:O(nlog2n) 平均时间复杂度:O(nlog2n) 空间复杂度:O(1) 稳定性:不稳定 堆排序主要分三个函数: 1 调整成堆结构 void H

建堆,以及对堆排序

建堆,以及堆排序 代码1: #include<stdio.h> int h[101];//用来存放堆的数组 int n;//用来存储堆中元素的个数,就是堆的大小 //交换函数,用来交换堆中的俩个元素的值 void swap(int x,int y) { int t; t=h[x]; h[x]=h[y]; h[y]=t; } //向下调整函数 void siftdown(int i) {//传入一个须要向下调整的的节点编号i,这里传入1.即从堆的顶点開始向下调整 int t,flag=0;//f

堆排序总结

堆排序 概念: 第一个非叶子节点: 小于size/2的部分; 非叶子节点的区间: [0, size/2); (注意是左闭右开) 最大堆:满足父节点head, arr[head]<=arr[2*head+1] && arr[head]<=arr[2*head+2] 非叶子节点的子树才需要调整(没有子节点的树何谈调整) ps: 全文使用的下标均是从0开始 堆排序过程 初始化堆: 从size/2到0调整堆, 使得堆满足条件; 调整堆: 如果head在非叶子节点的区间, 即head 属