VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/table/avl_RemoveNode.cpp.h

Last change on this file was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 4.7 KB
Line 
1/* $Id: avl_RemoveNode.cpp.h 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * kAVLRemove2 - Remove specific node (by pointer) from an AVL tree.
4 */
5
6/*
7 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/**
39 * Removes the specified node from the tree.
40 *
41 * @returns Pointer to the removed node (NULL if not in the tree)
42 * @param ppTree Pointer to the AVL-tree root structure.
43 * @param pNode Pointer to the node to be removed.
44 *
45 * @remark This implementation isn't the most efficient, but it's relatively
46 * short and easier to manage.
47 */
48KAVL_DECL(PKAVLNODECORE) KAVL_FN(RemoveNode)(PPKAVLNODECORE ppTree, PKAVLNODECORE pNode)
49{
50#ifdef KAVL_EQUAL_ALLOWED
51 /*
52 * Find the right node by key together with the parent node.
53 */
54 KAVLKEY const Key = pNode->Key;
55 PKAVLNODECORE pParent = NULL;
56 PKAVLNODECORE pCurNode = KAVL_GET_POINTER_NULL(ppTree);
57 if (!pCurNode)
58 return NULL;
59 while (KAVL_NE(pCurNode->Key, Key))
60 {
61 pParent = pCurNode;
62 if (KAVL_G(pCurNode->Key, Key))
63 {
64 if (pCurNode->pLeft != KAVL_NULL)
65 pCurNode = KAVL_GET_POINTER(&pCurNode->pLeft);
66 else
67 return NULL;
68 }
69 else
70 {
71 if (pCurNode->pRight != KAVL_NULL)
72 pCurNode = KAVL_GET_POINTER(&pCurNode->pRight);
73 else
74 return NULL;
75 }
76 }
77
78 if (pCurNode != pNode)
79 {
80 /*
81 * It's not the one we want, but it could be in the duplicate list.
82 */
83 while (pCurNode->pList != KAVL_NULL)
84 {
85 PKAVLNODECORE pNext = KAVL_GET_POINTER(&pCurNode->pList);
86 if (pNext == pNode)
87 {
88 if (pNode->pList != KAVL_NULL)
89 KAVL_SET_POINTER(&pCurNode->pList, KAVL_GET_POINTER(&pNode->pList));
90 else
91 pCurNode->pList = KAVL_NULL;
92 pNode->pList = KAVL_NULL;
93 return pNode;
94 }
95 pCurNode = pNext;
96 }
97 return NULL;
98 }
99
100 /*
101 * Ok, it's the one we want alright.
102 *
103 * Simply remove it if it's the only one with they Key, if there are
104 * duplicates we'll have to unlink it and insert the first duplicate
105 * in our place.
106 */
107 if (pNode->pList == KAVL_NULL)
108 KAVL_FN(Remove)(ppTree, pNode->Key);
109 else
110 {
111 PKAVLNODECORE pNewUs = KAVL_GET_POINTER(&pNode->pList);
112
113 pNewUs->uchHeight = pNode->uchHeight;
114
115 if (pNode->pLeft != KAVL_NULL)
116 KAVL_SET_POINTER(&pNewUs->pLeft, KAVL_GET_POINTER(&pNode->pLeft));
117 else
118 pNewUs->pLeft = KAVL_NULL;
119
120 if (pNode->pRight != KAVL_NULL)
121 KAVL_SET_POINTER(&pNewUs->pRight, KAVL_GET_POINTER(&pNode->pRight));
122 else
123 pNewUs->pRight = KAVL_NULL;
124
125 if (pParent)
126 {
127 if (KAVL_GET_POINTER_NULL(&pParent->pLeft) == pNode)
128 KAVL_SET_POINTER(&pParent->pLeft, pNewUs);
129 else
130 KAVL_SET_POINTER(&pParent->pRight, pNewUs);
131 }
132 else
133 KAVL_SET_POINTER(ppTree, pNewUs);
134 }
135
136 return pNode;
137
138#else
139 /*
140 * Delete it, if we got the wrong one, reinsert it.
141 *
142 * This ASSUMS that the caller is NOT going to hand us a lot
143 * of wrong nodes but just uses this API for his convenience.
144 */
145 KAVLNODE *pRemovedNode = KAVL_FN(Remove)(pRoot, pNode->Key);
146 if (pRemovedNode == pNode)
147 return pRemovedNode;
148
149 KAVL_FN(Insert)(pRoot, pRemovedNode);
150 return NULL;
151#endif
152}
153
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette