数据结构与算法分析C++习题6.13答案

(a)

void deleteMin(Comparable& minItem)
	{
		if (isEmpty())
		{
			throw UnderflowException{};
		}
		minItem = std::move(arr[1]);
		Comparable temp = std::move(arr[currentSize--]);
		int hole = 1;
		vector<int> indices;
		//从根结点开始找到叶子结点的一条路径(记录下标),保证路径上的结点为其双亲的最小孩子结点。
		//比较次数为logN
		for (int i = hole * 2; i <= currentSize; i *= 2) 
		{
			if (i < currentSize && arr[i + 1] < arr[i])
			{
				i++;
			}
			indices.push_back(i);
		}

		//二分查找插入元素在路径中的插入位置,用low记录插入位置。比较次数为loglogN
		int mid, low = 0, high = indices.size() - 1;
		while (low <= high)
		{
			mid = low + (high - low) / 2;
			if (arr[indices[mid]] < temp)
			{
				low = mid + 1;
			}
			else if (arr[indices[mid]] > temp)
			{
				high = mid - 1;
			}
			else
			{
				low = mid;
				break;
			}
		}
		int i;
		hole = 1;
		//调整路径上元素的位置
		for (i = 0; i < low; i++)
		{
			arr[hole] = std::move(arr[indices[i]]);
			hole = indices[i];
		}

		//将待插元素插入
		arr[hole] = std::move(temp);


	}

(b)

void deleteMin(Comparable& minItem)
	{
		if (isEmpty())
		{
			throw UnderflowException{};
		}
		minItem = std::move(arr[1]);
		Comparable temp = std::move(arr[currentSize--]);
		if (currentSize == 1)
		{
			arr[1] = std::move(temp);
			return;
		}
		int hole = 1;
		vector<int> indices;
		//从根结点开始找到叶子结点的一条路径(记录下标,在logN - loglogN层停止),保证路径上的结点为其双亲的最小孩子结点。
		//比较次数为logN - loglogN
		for (int i = hole * 2, k = 0; i <= currentSize && k < log(currentSize) - log(log(currentSize)); i *= 2, k++) 
		{
			if (i < currentSize && arr[i + 1] < arr[i])
			{
				i++;
			}
			indices.push_back(i);
		}
		int mid, low, high;
		//如果插入位置在停止位置之前,则在前logN - loglogN个元素中二分查找插入位置
		//找路径比较次数logN -loglogN, 二分查找比较次数最多loglogN,总的比较次数logN
		if (indices.size() > 0 && temp <= arr[indices.size() - 1])
		{
			low = 0; 
		}
		//如果插入位置在停止位置之后,则继续找到叶子结点的路径(记录路径下标),但是查找插入位置只在后loglogN个元素二分查找插入位置
		//找路径比较次数logN, 二分查找比较次数logloglogN,总的比较次数logN + logloglogN;
		else
		{
			int i;
			if (indices.size() > 0)
			{
				i = indices[indices.size() - 1] * 2;
				low = indices.size() -1;
			}
			else
			{
				i = hole * 2;
				low = 0;
			}
			for (; i <= currentSize; i *= 2)
			{
				if (i < currentSize && arr[i + 1] < arr[i])
				{
					i++;
				}
				indices.push_back(i);
			}
		}

		high = indices.size() - 1;

		while (low <= high)
		{
			mid = low + (high - low) / 2;
			if (arr[indices[mid]] < temp)
			{
				low = mid + 1;
			}
			else if (arr[indices[mid]] > temp)
			{
				high = mid - 1;
			}
			else
			{
				low = mid;
				break;
			}
		}
		int i;
		hole = 1;
		//调整路径上元素的位置
		for (i = 0; i < low; i++)
		{
			arr[hole] = std::move(arr[indices[i]]);
			hole = indices[i];
		}

		//将待插元素插入
		arr[hole] = std::move(temp);


	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值