算法导论第六章 -- 堆排序

堆排序:主要是二叉堆,是一个数组,可以近似看作是一棵完全二叉树。最坏情况运行时间为 n * log (n);


主要性质:

1.对于任意一个下标index,书上写的是左子女的下标为 2 * index,右子女为   2  *  index + 1;但是在实际编程中,下标是从0开始的,所以下标的变化应该为:

左子女为2 * index + 1, 右子女为 2 * index + 2;

2.最大(小)堆:对于任意一个非叶节点,它的值都大于(小于)等于它的子女节点。

下面是自己写的代码,只针对int型,并且针对最大堆,如果要对其他类型进行堆排序,那么就要重载操作符。

heap.h

#ifndef HEAP_H
#define HEAP_H

#include <iostream>
#include <vector>

class MyHeap
{
public:
	MyHeap(std::vector<int>&);        //用vector来建立并保存数组,
	int getMax();                     //返回当前的最大值(根节点,数组的第一个元素)
	void heapSort();                  //堆排序
	void printVector();               //打印当前数组
	void buildMaxHeap(int size);      //用当前保存在heap对象里面的数组构造最大堆
	~MyHeap();              
private:
 	void maxHeaplify(std::vector<int>&,int index);         //维护最大堆的函数
	std::vector<int> array;
	void swap(int&, int&);                             //交换两个index
	std::vector<int>::size_type size;                      //记录未排好序的数组的长度。
};


#endif


3.上面实现堆排序的几个重要的函数:

1)maxHeaplify(),这个函数接受一个数组和一个下标,用这个下标计算它的左右子女,进而和左右子女比较,如果根节点不是

最大的话,那就不满足最大堆的性质,那么就要把根节点和子女中的最大值坐交换,并且记录下被交换子女的index,

然后再递归地调用这个函数,直到节点满足最大堆的性质为止。

2)heapSort() buildMaxHeap() 这两个函数都会调用上面的函数,但是值得注意的是:buildMaxHeap()这个函数的起始条件是

从第一个非叶节点的节点开始调用maxHeaplify(),而第一个非叶节点的下标(按照书上来说是:数组大小 / 2 并向下取整),

但是在实际编程中的非叶节点的下标为:(数组大小 / 2 - 1)。

下面是cpp文件:

#include "heap.h"

/*为什么在堆排序的时候下面这个函数只用从根节点开始:
因为排序之前我们已经让堆具有了最大堆的性质,所以交换节点之后根节点会违反最大堆的性质,而其他节点
会保持相应的最大堆的性质,没有必要再从第一个非叶节点开始调用函数。
为什么不会把最大值再次调整到堆顶:
因为我们已经把未排序的数组的大小“改变了”-通过一个成员变量,所以最大值交换之后就会固定了,不会再被交换。
*/


void MyHeap::buildMaxHeap(int size)
{
	for (int i = size/2 - 1; i >= 0; --i)
	{
		this->maxHeaplify(this->array,i);
	}
}

int MyHeap::getMax()
{
	return array[0];
}

void MyHeap::heapSort()                      // Heap Sort;
{
	std::vector<int>::size_type start = this->size - 1;
	--this->size;
	while(start > 0)
	{
		std::cout << this->size << std::endl;
		this->swap(array[0],array[start]);
		this->buildMaxHeap(2);
		--this->size;
		--start;
	}

}	

void MyHeap::printVector()
{
	std::vector<int>::size_type size = array.size();
	for(std::vector<int>::size_type i = 0; i != size; ++i)
	{
		std::cout << array[i] << " ";
	}
	std::cout << std::endl;
}

MyHeap::MyHeap(std::vector<int>& row) : array(row),size(row.size())         //construct a heap as a Max-Heap;
{
	this->buildMaxHeap(array.size());
}

void MyHeap::maxHeaplify(std::vector<int>& target,int index)
{
	int left = index * 2 + 1;
	int right = index * 2 + 2;
	int maxIndex = index;

	if(left < this->size && target[index] < target[left])        //compare left child with this node,if left is bigger,then write down the max index;
	{
		maxIndex = left;
	}
	else
	{
		maxIndex = index;
	}

	if(right < this->size && target[maxIndex] < target[right])      //compare right child with max index,if right is bigger,then write down the max index;
	{
		maxIndex = right;
	}

	if(maxIndex != index)               //if 'root' is max, end this function
	{
		this->swap(target[maxIndex],target[index]);
		this->maxHeaplify(target,maxIndex);
	}
}

void MyHeap::swap(int& first, int& second)
{
	int current = first;
	first = second;
	second = current;
}

MyHeap::~MyHeap()
{
	std::cout << "Destroy Heap" << std::endl;
}




 

最后是主函数:简单试验:

#include "heap.h"

int main()
{
	int a[16] = {4,1,3,2,16,9,10,14,8,7,56,4,3,5,6,100};
	std::vector<int> v(a,a+16);
	MyHeap test(v);
	test.printVector();
	test.heapSort();
	test.printVector();
	return 0;
}

g++ -o heap.h heap.cpp main.cpp

经过实验,正常得到排序的结果





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值