(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);
}