c++---------数据结构—堆-----堆排序

这里只说一点,根据一个大小为n的数组,然后进行批量的建堆;其用的是Floyd算法,它首先在LastInetral_node=(n-2)>>1;

然后依次遍历其内点,然后进行下滤算法:(图借用邓俊辉的数据结构)

                  

               

可以看出,其时间复杂度为:一颗n个节点的完全二叉树,其内部节点为K= n/2 - 1 ;

从而就需要进行           \sum_{i=1}^{K} height(i)=O(n);

当然还有另一种蛮力算法,就是每次将元素插入堆的末尾,然后进行上滤;

明显时间复杂度为:\sum_{i=1}^{K}depth(i)=O(nlogn),越靠近底层,节点越多深度越深;并且在这么长的时间下,我们用AVL树,本可以做到全序,且时间复杂度也为O(nlogn),从而肯定有更好的办法,如Floyd算法;

堆排序的时间复杂度:因为就是先对数组进行建堆,然后每次都delete Max,即取出第一个元素,将其赋值给array[hi--];

建堆需要上面的Floyd算法;即O(n);然后再进行依次的删除操作,也就O(n)时间,所以总时间就是O(n),当然可能额外的空间可以优化为O(1);我写的算法里并没有;

但书中给出了解释:

即它使用原数组进行建堆,然后从头开始遍历,将每一步的根m(最大元素)与末尾(hi--)x交换,然后将x进行下滤,从而每一步下滤时间都不超过O(logn),因为需要迭代n次,从而总时间是O(nlogn);且辅助空间仅是swap的O(1)

                   

 但我的算法,是在堆中重新用了一个数组,从而辅助空间不能减少,但是时间复杂度为O(n),额外空间复杂度为O(n)

下面贴出我的堆的数据结构,当然不是优化版本,因为每一次插入操作,都需要复制一遍数组,我其实可以继承vector的;

template <typename T> 
class PQ
{
public:
	int size;
	PQ(int n=0) :size(n) {
		PQ_arr = new T[n];
	};
	//拷贝构造
	PQ(PQ &it)
	{
		size = it.size;
		delete PQ_arr;
		PQ_arr=new T[size];
		for (int i = 0; i < size; ++i)
		{
			PQ_arr[i] = it.value[i];
		}

	}

	PQ(const vector<T> &vec,int n):size(vec.size()) {
		PQ_arr = new T[size];
		int i = 0;
		for (auto it : vec)
		{
			PQ_arr[i++] = it;
		}
		heapify(n);
		
	};
	//复制构造
	PQ &operator=(const PQ &it)
	{
		size = it.size;
		delete []PQ_arr;
		PQ_arr = new T[size];
		for (int i = 0; i < size; ++i)
		{
			PQ_arr[i] = it.value[i];
		}
		return *this;
	}

	T &value(int i) 
	{
		return PQ_arr[i];
	}

	T &value(int i) const
	{
		return PQ_arr[i];
	}

	/*! overload stream operator << */
	friend  std::ostream & operator << (std::ostream & os, const PQ & _Q)
	{
		for (int i=0;i< _Q.size;++i)
		{
			os << _Q.value(i) << "   ";
		}
		return os;
	};

	void insert(T);
	T getMax();
	T delMax();

	~PQ()
	{
		delete []PQ_arr;
	}
private:
	void percolateDown(int n, int i);		//下滤
	void percolateUp(int i);					//上滤
	void heapify(int n);
	T* PQ_arr;
	
};

template <typename T>
T PQ<T>::getMax()
{
	return PQ_arr[0];
}

template <typename T>
void PQ<T>::insert(T e)
{
	//就这么慢吧,可以用vector来实现
	T *temp = new T[size + 1];
	for (int i = 0; i < size; ++i)
	{
		temp[i] = PQ_arr[i];
	}
	delete PQ_arr;
	temp[size] = e;
	PQ_arr = temp;
	size++;
	percolateUp(size-1);
}

template <typename T>
void PQ<T>::percolateUp(int i)
{
	while ((i - 1) >= 0)
	{
		int parent = (i - 1) >> 1;
		if (PQ_arr[i] > PQ_arr[parent])	std::swap(PQ_arr[i], PQ_arr[parent]);
		else break;
		i = parent;
	}
}

template <typename T>
void PQ<T>::percolateDown(int n, int i)
{
	T old = PQ_arr[i];
	int __chlid = i;
	while (true)
	{
		if (((i << 1) + 1 < n) && old < PQ_arr[(i << 1) + 1]) __chlid = (i << 1) + 1;
		if (((i << 1) + 2 < n) && PQ_arr[__chlid] < PQ_arr[(i << 1) + 2]) __chlid = (i << 1) + 2;
		if (__chlid == i)	break;
		PQ_arr[i] = PQ_arr[__chlid];
		i = __chlid;
	}
	PQ_arr[i] = old;
}

template <typename T>
T PQ<T>::delMax()
{
	std::swap(PQ_arr[0], PQ_arr[size-1]);
	percolateDown(size - 1, 0);
	--size;
	return PQ_arr[size ];
}

template <typename T>
void PQ<T>::heapify(int n)
{
	int j = (n - 2) >> 1;
	for (int i = j; i >= 0; --i)
	{
		percolateDown(n,i);
	}
}

void Heap_sort(vector<int> &arr)
{
	//先进行一次堆操作
	if (arr.size() == 1)	return;
	PQ<int> heap_(arr, arr.size());
	int hi = arr.size() - 1;
	while (hi>=0)
	{
		int max = heap_.delMax();
		arr[hi--] = max;
	}

}
int main()
{
    vector<int> iyu = { 0,3,1,5,4,2 };
	
	PQ<int> heap_my(iyu, iyu.size());
	std::cout << heap_my << endl;
	heap_my.insert(7);
	std::cout << heap_my << endl;
	int var=heap_my.delMax();
    std::cout << var<< endl;
	std::cout << heap_my << endl;

	Heap_sort(iyu);

    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值