第6章 堆排序

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define leftChild(i) (2*(i)+1)
//交换
void swap(int *a, int i, int j)
{
    int tmp = a[i];
    a[i] = a[j];
    a[j] = tmp;
}
//堆下溯
void maxHeapify(int *a, int i, int n)
{
    int child, tmp;
    for (tmp = a[i]; leftChild(i)<n; i = child){
        child = leftChild(i);
        if (child != n - 1 && a[child] < a[child + 1]) ++child;
        if (tmp < a[child]) a[i] = a[child];
        else break;
    }
    a[i] = tmp;
}
//建立最大堆
void buildMaxHeap(int *a, int n)
{
    for (int i = n / 2; i >= 0; --i)
        maxHeapify(a, i, n);
}
//堆排序
void heapSort(int *a, int n)
{
    for (int i = n / 2; i >= 0; --i)
        maxHeapify(a, i, n);
    for (int i = n - 1; i > 0; --i){
        swap(a, 0, i);
        maxHeapify(a, 0, i);
    }
}
typedef struct _stack{
    int *arr;
    int pos;
}stack;
//创建一个空的优先队列
stack create(int capacity)
{
    stack s;
    s.pos = -1;
    s.arr = (int*)malloc(capacity*sizeof(int));
    memset(s.arr, 0, capacity*sizeof(int));
    return s;
}
//返回优先队列最大元素
int maxOfStack(stack &s)
{
    return s.arr[0];
}
//返回最大元素并删除
int extractMax(stack &s)
{
    swap(s.arr,0,s.pos);
    --s.pos;
    return s.arr[s.pos + 1];
}
//增大指定元素到key
void increaseKey(stack &s, int i, int key)
{
    if (i > s.pos) return;
    if (key < s.arr[i]) return;
    s.arr[i] = key;
    while (i > 0 && s.arr[i] > s.arr[(i - 1) / 2]){
        swap(s.arr, i, (i - 1) / 2);
        i = (i - 1) / 2;
    }
}
//插入元素
void insert(stack &s, int val)
{
    ++s.pos;
    s.arr[s.pos] = val;
    increaseKey(s, s.pos, val);
}

//思考题6.2,d叉堆
void increaseKeyD(int *a, int i, int key,int d)
{
    if (a[i] > key) return;
    a[i] = key;
    while (i > 0 && a[i] > a[(i - 1) / d]){
        swap(a, i, (i - 1) / d);
        i = (i - 1) / d;
    }
}

//思考题6.3,young氏矩阵
void maxHeapYoung(int *a, int i, int j, int m, int n)
{
    int tmp, x, y;
    while (tmp = a[i*n + j]){
        x = i; y = j;
        if (x < m - 1 && y < n - 1){
            if (a[x*n + y + 1] > a[(x + 1)*n + y]) ++x;
            else ++y;
        }
        else if (x < m - 1) ++x;
        else if (y < n - 1) ++y;
        else break;
        if (tmp > a[x*n + y]) a[i*n + j] = a[x*n + y];
        else break;
        i = x; j = y;
        a[i*n + j] = tmp;
    }
}
int main()
{
    int a[] = { 3, 5, 7, 20,-1,-5,9, 8, 6, 4, 1 };
    stack s = create(20);
    for (int i = 0; i < 11; ++i)
        insert(s, a[i]);
    for (int i = 0; i <= s.pos; ++i)
        printf("%d\t", s.arr[i]);
    printf("\n");
    int b[] = { 100, 5, 12, 3, 8, 14, 4, 9, 16 };
    maxHeapYoung(b, 0, 0, 3, 3);
    for (int i = 0; i < 9; ++i)
        printf("%d\t", b[i]);
    printf("\n");
}

堆:stack

队列:queue

优先队列:priority_queue

  for all

size_type

value_type

container_type

A a;

A a(c);

关系运算  ==  !=  <  <=  >  >=

a.empty();

a.size();

swap(a,b);

a.swap(b);

  for stack

stack<int>,默认基于deque实现;可以指定为list/vector,stack<int,vector<int>>

s.pop();  删除

s.push(item);  入栈

s.emplace(args);  入栈

s.top();  返回

  for queue

queue<int>,默认基于deque,可指定list/vector,queue<int,vector<int>>

q.front();

q.back();

q.push(item);

q.emplace(args);

q.pop();

  for priority_queue
prioriry_queue<int>默认基于vector,less<int>,可指定deque,greater<int>,priority_queue<int,deque<int>,greater<int>>
pq.top();
pq.push(item);
pq.emplace(args);
pq.pop();
时间: 2024-07-30 00:25:34

第6章 堆排序的相关文章

【算法导论】学习笔记——第6章 堆排序

堆这个数据结构应用非常广泛,数字图像处理的算法里也见过.似乎记得以前老师上课说需要用树结构实现堆排序,看了一下算法导论才明白其精髓.堆虽然是一棵树,但显然没必要非得用树结构实现堆排序.堆排序的性质很好,算法时间复杂度为O(nlgn). 1. 堆排序的简要说明.二叉堆可以分为两种形式:最大堆和最小堆.在最大堆中,最大堆性质是指除了根以外的所有结点i都要满足: A[PARENT(i)] >= A[i]:在最小堆中,最小堆性质是指除了根以外的所有结点i都要满足: A[PARENT(i)] <= A[

算法导论 第6章 堆排序

堆数据结构实际上是一种数组对象,是以数组的形式存储的,但是它可以被视为一颗完全二叉树,因此又叫二叉堆.堆分为以下两种类型: 大顶堆:父结点的值不小于其子结点的值,堆顶元素最大 小顶堆:父结点的值不大于其子结点的值,堆顶元素最小 堆排序的时间复杂度跟合并排序一样,都是O(nlgn),但是合并排序不是原地排序(原地排序:在排序过程中,只有常数个元素是保存在数组以外的空间),合并排序的所有元素都被拷贝到另外的数组空间中去,而堆排序是一个原地排序算法. 1.在堆排序中,我们通常使用大顶堆来实现,由于堆在

算法导论 第6章 堆排序(简单选择排序、堆排序)

堆数据结构实际上是一种数组对象,是以数组的形式存储的,可是它能够被视为一颗全然二叉树,因此又叫二叉堆.堆分为下面两种类型: 大顶堆:父结点的值不小于其子结点的值,堆顶元素最大 小顶堆:父结点的值不大于其子结点的值,堆顶元素最小 堆排序的时间复杂度跟合并排序一样,都是O(nlgn),可是合并排序不是原地排序(原地排序:在排序过程中,仅仅有常数个元素是保存在数组以外的空间),合并排序的全部元素都被复制到另外的数组空间中去,而堆排序是一个原地排序算法. 1.在堆排序中,我们通常使用大顶堆来实现,因为堆

第六章 堆排序 6.5 优先队列

package chap06_Heap_Sort; import static org.junit.Assert.*; import java.util.ArrayList; import java.util.Arrays; import org.junit.Test; /** * 优先队列,二叉堆数组实现,数组的size最好大一些,至少比里面的堆大一些,来实现堆的扩展(插入元素) * * @author xiaojintao * */ public class PriorityQueue {

算法导论笔记——第六七章 堆排序和快速排序

第六章 堆排序 最小堆和最大堆:近似的完全二叉树 A[parent(i)]<=A[i]或者A[parent(i)]>=A[i] 建堆复杂度O(n) 排序O(nlgn) 实际应用中,快速排序一般优于堆排序.可用于优先队列等. 在一个包含n个元素的堆中,所有优先队列的操作均可在O(lgn)时间内完成. 第七章 快速排序 与归并排序一样用分治思想 主元pivot可随机生成

第六章 堆排序

以后尽量能用迭代就别用递归啊,递归只是让自己轻松了,但是却增加了电脑的负担. package chap06_Heap_Sort; import static org.junit.Assert.*; import java.util.Arrays; import org.junit.Test; public class SortAlorithms { /** * 返回当前下标下父节点的下标 * * @param i * @return */ protected static int parent(

《算法导论》 - 第6章 - 堆排序 - 习题解答

序 GitHub 见solution.txt 6.1 堆 6.1-1 在高度为h的堆中,最多元素为2(h+1)?1个,最少元素有 2h+1 个 6.1-3 最大堆的特性是除了根结点外的每个结点都有A[PARENT(i)]>=A[i]故,在一个最大堆的某颗子树中最大元素必然位于该子树的根上. 6.1-4 根据最大堆的性质,任何子树的子结点都小于根节点,故整棵树的最小元素必然位于堆的最底层或者倒数第二层的叶子结点. 6.1-5 不一定,是最小堆也可能是最大堆 6.1-6 不是,画出相应堆结构发现元素

第6章 堆排序 java实现 最简版

只考虑int类型的排序,以后考虑泛型实现. 1 public class Heap { 2 3 public int heap_size;//在build_max_heap中初始化,由heap_sort自动调用 4 5 public int parent(int i){ 6 return (i - 1) / 2; 7 } 8 public int left(int i){ 9 return 2 * i + 1; 10 } 11 public int right(int i){ 12 return

算法导论第六章 堆排序

堆的时间复杂度是建O(n),时间复杂度为堆排序O(NLogN),细节如以下的算法看到: #include <iostream> using namespace std; void swap(int &i,int &j) { int temp=i; i=j; j=temp; } void shiftDown(int *A, int start,int len) { int temp=A[start]; int i=start; int j=2*i+1; while (j<l

第六章——堆排序

一 堆 堆给人的感觉是一个二叉树,但是其本质是一种数组对象,因为对堆进行操作的时候将堆视为一颗完全二叉树,树种每个节点与数组中的存放该节点值的那个元素对应.所以堆又称为二叉堆,堆与完全二叉树的对应关系如下图所示: 二叉堆可以分为两种形式:最大堆和最小堆.在这两种堆中,结点的值都要满足堆的性质. 在最大堆中,最大堆的性质是指除了根以外的所有结点i都要满足: A[PARENT(i)]>=A[i] 也就是说,某个结点的值至多与其父结点一样大.因为,堆中的最大元素存放在根结点中:并且,在任一子树中,该子