c 语言双指针的问题

2022-12-28 10:37:14 +08:00
 Or2

https://www.cs.yale.edu/homes/aspnes/pinewiki/C(2f)AvlTree.html

   3 typedef struct avlNode *AvlTree;
   5 /* empty avl tree is just a null pointer */
   6 
   7 #define AVL_EMPTY (0)
   8 
   9 struct avlNode {
  10     struct avlNode *child[2];    /* left and right */
  11     int key;
  12     int height;
  13 };
  14 
  87 static void
  88 avlRotate(AvlTree *root, int d)
  89 {
  90     AvlTree oldRoot;
  91     AvlTree newRoot;
  92     AvlTree oldMiddle;
  93 
  94     oldRoot = *root;
  95     newRoot = oldRoot->child[d];
  96     oldMiddle = newRoot->child[!d];
  97 
  98     oldRoot->child[d] = oldMiddle;
  99     newRoot->child[!d] = oldRoot;
 100     *root = newRoot;
 101 
 102     /* update heights */
 103     avlFixHeight((*root)->child[!d]);   /* old root */
 104     avlFixHeight(*root);                /* new root */
 105 }
 106 
 107 
 108 /* rebalance at node if necessary */
 109 /* also fixes height */
 110 static void
 111 avlRebalance(AvlTree *t)
 112 {
 113     int d;
 114 
 115     if(*t != AVL_EMPTY) {
 116         for(d = 0; d < 2; d++) {
 117             /* maybe child[d] is now too tall */
 118             if(avlGetHeight((*t)->child[d]) > avlGetHeight((*t)->child[!d]) + 1) {
 119                 /* imbalanced! */
 120                 /* how to fix it? */
 121                 /* need to look for taller grandchild of child[d] */
 122                 if(avlGetHeight((*t)->child[d]->child[d]) > avlGetHeight((*t)->child[d]->child[!d])) {
 123                     /* same direction grandchild wins, do single rotation */
 124                     avlRotate(t, d);
 125                 } else {
 126                     /* opposite direction grandchild moves up, do double rotation */
 127                     avlRotate(&(*t)->child[d], !d);
 128                     avlRotate(t, d);
 129                 }
 130 
 131                 return;   /* avlRotate called avlFixHeight */
 132             }
 133         }
 134                   
 135         /* update height */
 136         avlFixHeight(*t);
 137     }
 138 }
 139 
 140 /* insert into tree */
 141 /* this may replace root, which is why we pass
 142  * in a AvlTree * */
 143 void
 144 avlInsert(AvlTree *t, int key)
 145 {
 146     /* insertion procedure */
 147     if(*t == AVL_EMPTY) {
 148         /* new t */
 149         *t = malloc(sizeof(struct avlNode));
 150         assert(*t);
 151 
 152         (*t)->child[0] = AVL_EMPTY;
 153         (*t)->child[1] = AVL_EMPTY;
 154 
 155         (*t)->key = key;
 156 
 157         (*t)->height = 1;
 158 
 159         /* done */
 160         return;
 161     } else if(key == (*t)->key) {
 162         /* nothing to do */
 163         return;
 164     } else {
 165         /* do the insert in subtree */
 166         avlInsert(&(*t)->child[key > (*t)->key], key);
 167 
 168         avlRebalance(t);
 169 
 170         return;
 171     }
 172 }
  1. 这个实现中,avlRotate, avlRebalance, avlInsert 都用了双指针,我的理解是作者特意用了双指针。 双指针相比于直接用指针有什么特别的优势么?
  2. avl tree ,red black tree 还有什么写的很好的可以多学习下的实现么?
861 次点击
所在节点    问与答
2 条回复
stein42
2022-12-28 12:10:27 +08:00
这个通常叫二级指针吧。

AvlTree 定义为指向根结点的指针。
对 AvlTree 进行修改,它的根结点可能改变,所以定义 AvlTree 为 AvlNode* 是必要的。

传参都是传 AvlTree*,相当于 AvlNode**,这是一个二级指针。

另一种定义方法是结构体:
struct AvlTree { AvlNode* root; }
结构体的好处是还可以包含其它字段,例如树的结点数量。
没有其它字段的话用指针也是可以的。
Or2
2022-12-28 12:38:14 +08:00
哈哈,豁然开朗啊!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/905091

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX