《算法导论》第14章 数据结构的扩张 (2)


在上一节中,我们为树结点添加size域表示每颗子树的大小,即包含的结点个数,扩张了
二叉查找树为其增加顺序统计量的查找功能。更为自然的想法是直接添加顺序统计量rank域
到每个树结点上。这一节我们就来看下在这样的设计下,如何扩张来完成上一节相同的功能。

当我们插入一个结点到二叉树中,假设它的顺序统计量为5,那么之前二叉树中顺序统计量
大于5的结点都要更新。也就是说插入一个新结点到对应的位置后,要不断地查找其后继,
完成rank域的更新。所以可以结合习题14.2-1,再添加两个指针域prev和next指向前趋和后继,
使查找前趋和后继在O(1)内完成。

下面来看具体代码。

// 添加三个新域 typedef struct _BSTNode { struct _BSTNode *left, *right, *parent; int key; char *value; struct _BSTNode *prev, *next; int rank; } BSTNode; // 对于prev和next指针的维护,插入结点分两种情况: // 1.新插入结点newNode是其父结点P的左子结点,说明P->prev < newNode < P // 2.新插入结点newNode是其父结点P的右子结点,说明P < newNode < P->next // // 对于rank域,如果newNode没有前趋,那么rank置为1,否则置为newNode前趋的rank值加1 // 之后开始迭代更新,将newNode的所有后继的rank值都加1。 void bst_insert(BSTNode **root, BSTNode *newNode) { // Locate insert location BSTNode *pNode = NULL; BSTNode *node = *root; while (node != NULL) { pNode = node; if (newNode->key < node->key) node = node->left; else node = node->right; } // Link newNode to pNode newNode->parent = pNode; // Link pNode to newNode // 新逻辑:维护prev, next if (pNode == NULL) { *root = newNode; } else if (newNode->key < pNode->key) { pNode->left = newNode; // newNode is between pNode->prev and pNode if (pNode->prev != NULL) pNode->prev->next = newNode; newNode->prev = pNode->prev; pNode->prev = newNode; newNode->next = pNode; } else { pNode->right = newNode; // newNode is between pNode and pNode->next if (pNode->next != NULL) pNode->next->prev = newNode; newNode->next = pNode->next; newNode->prev = pNode; pNode->next = newNode; } // 新逻辑:维护rank域 if (newNode->prev == NULL) newNode->rank = 1; else newNode->rank = newNode->prev->rank + 1; BSTNode *succesor = newNode; while ((succesor = succesor->next) != NULL) { succesor->rank += 1; } } // Select和Rank操作变得格外简单 BSTNode *bst_os_select(BSTNode *node, int i) { while (node != NULL) { if (node->rank == i) return node; else if (node->rank > i) node = node->left; else node = node->right; } return NULL; } int bst_os_rank(BSTNode *node) { return node->rank; }

通过这一节和上一节的对比,可以看出在步骤(2)中对基础数据结构添加不同的域,会对
步骤(3)和(4)改写和添加新的操作产生很大影响。因此,在扩张数据结构时可以采用
试错法,尝试添加不同的域,权衡各种方案的优劣。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值