红黑树

 

 

  1 import java.util.Random;

  2 

  3 

  4 public class RBTree 

  5 {

  6     

  7     private Node root;

  8     

  9     

 10     public RBTree(int[] array)

 11     {

 12         for (int i : array) insert(i);

 13     }

 14     

 15     private Node search(int key, Node node)

 16     {

 17         if (node == null) return null;

 18         int compare = compare(key, node.key);

 19         

 20         if (compare == 0) return node;

 21         if (compare > 0) 

 22             return search(key, node.right);

 23         else 

 24             return search (key, node.left);

 25     }

 26     

 27     /*

 28      * 插入节点

 29      */

 30     public boolean insert(int key)

 31     {

 32         Node node = new Node(key);

 33         node.color = 'R';

 34         

 35         Node parent = null, current = root;

 36         int compare = 0;

 37         

 38         /*

 39          * 寻找插入节点的父节点

 40          */

 41         while (current != null) {

 42             parent = current;

 43             compare = compare(key, current.key);

 44                 

 45             if (compare == 0) return false;

 46             

 47             if (compare == 1)

 48                 current = current.right;

 49             else

 50                 current = current.left;

 51         }

 52 

 53         // 添加新节点

 54         if (parent == null) {

 55             root = node;

 56         }

 57         else {

 58             node.parent = parent;

 59             if (compare == 1) {

 60                 parent.right = node;

 61             }

 62             else { 

 63                 parent.left = node;

 64             }

 65         }

 66         

 67         insertFixup(node);

 68         return true;

 69     }

 70     

 71     private void insertFixup(Node node)

 72     {

 73         while (node != root && node.parent.color == 'R') {

 74             // 父节点为祖父节点的左节点

 75             if (node.parent == node.parent.parent.left) {

 76                 Node uncle = node.parent.parent.right;

 77                 /*

 78                  * 父节点与叔叔节点都是红色

 79                  * 将父节点与叔叔节点变成黑色

 80                  * 将祖父节点变成红色

 81                  * 当前节点指向组父节点 

 82                  */

 83                 if (uncle != null && uncle.color == 'R') {

 84                     node.parent.color = 'B';

 85                     uncle.color = 'B';

 86                     uncle.parent.color = 'R';

 87                     node = node.parent.parent;

 88                 }

 89                 else {

 90                     /*

 91                      * 叔叔节点是黑色且node为右孩子

 92                      * 当前结点指向父节点

 93                      * 以当前结点为中心左旋

 94                      */

 95                     if (node == node.parent.right) {

 96                         node = node.parent;

 97                         leftRotate(node);

 98                     }

 99                     

100                     /*

101                      * 叔叔节点是黑色且node为左孩子

102                      * 父节点变为黑色,组父节点变为红色

103                      * 以祖父节点为中心右旋

104                      */

105                     node.parent.color = 'B';

106                     node.parent.parent.color = 'R';

107                     rightRotate(node.parent.parent);

108                 }

109             }

110             else {

111             // 父节点为祖父节点的右节点

112                 Node uncle = node.parent.parent.left;

113                 

114                 // 操作与上面相反

115                 if (uncle != null && uncle.color == 'R') {

116                     node.parent.color = 'B';

117                     uncle.color = 'B';

118                     uncle.parent.color = 'R';

119                     node = node.parent.parent;

120                 }

121                 else {

122                     if (node == node.parent.left) {

123                         node = node.parent;

124                         rightRotate(node);

125                     }

126                     node.parent.color = 'B';

127                     node.parent.parent.color = 'R';

128                     leftRotate(node.parent.parent);

129                 }

130             }

131         }

132         root.color = 'B';

133     }

134     

135     private void deleteFixup(Node node)

136     {

137         if (node == null) return;

138         

139         while (node != root && node.color == 'B') {

140             // node为父节点的左子节点

141             if (node == node.parent.left) {

142                 Node sibling = node.parent.right;

143                 

144                 /*

145                  * 当前结点为黑色且兄弟节点为红色

146                  * 将父节点染成红色,兄弟节点染成黑色

147                  * 针对父节点最一次左旋

148                  */

149                 if (sibling.color == 'R') {

150                     sibling.color = 'B';

151                     sibling.parent.color = 'R';

152                     leftRotate(node.parent);

153                     sibling = node.parent.right;

154                 }

155                 

156                 /*

157                  * 当前结点和兄弟节点为黑色,兄弟节点的子节点都为黑色

158                  * 将当前节点和兄弟节点抽出一重黑色加到父节点上

159                  * 把父节点当成新的节点继续计算

160                  */

161                 if (sibling.left.color == 'B' 

162                     && sibling.right.color == 'B') 

163                 {

164                     sibling.color = 'R';

165                     node = node.parent;

166                 }

167                 else {

168                     /*

169                      * 当前节点和兄弟节点为黑色,兄弟的左子节点为红色

170                      * 把兄弟节点染红,兄弟左子节点染黑

171                      * 以兄弟节点位置点右旋

172                      */

173                     if (sibling.right.color == 'B') {

174                         sibling.left.color = 'B';

175                         sibling.color = 'R';

176                         rightRotate(sibling);

177                         sibling = node.parent.right;

178                     }

179                     

180                     /*

181                      * 当前结点和兄弟节点为黑色,兄弟右子节点为红色

182                      * 把兄弟节点染成当前结点的父节点的颜色

183                      * 将当前节点的父节点染成黑色

184                      * 兄弟节点有子节点染成黑色

185                      * 以当前节点的父节点为支点左旋

186                      */

187                     sibling.color = node.parent.color;

188                     node.parent.color = 'B';

189                     sibling.right.color = 'B';

190                     leftRotate(node.parent);

191                     node = root;

192                 }

193             }

194             // node为父节点的右子节点

195             else {

196                 Node sibling = node.parent.left;

197                 

198                 /*

199                  * 当前结点为黑色,兄弟节点为红色

200                  * 将兄弟节点染成黑色

201                  * 当前结点的父节点染成红色

202                  * 以当前节点的父节点进行右旋

203                  */

204                 if (sibling.color == 'R') {

205                     sibling.color = 'B';

206                     sibling.parent.color = 'R';

207                     rightRotate(node.parent);

208                     sibling = node.parent.left;

209                 }

210                 

211                 /*

212                  * 当前结点和兄弟节点为黑色

213                  * 把当前结点和兄弟节点抽取一重黑色到父节点上

214                  * 把当前节点当作新的节点重新计算

215                  */

216                 if (sibling.left.color == 'B' && sibling.right.color == 'B') {

217                     sibling.color = 'R';

218                     sibling.parent.color = 'B';

219                     node = node.parent;

220                 }

221                 else {

222                     /*

223                      * 当前结点和兄弟节点为黑色,兄弟的右子节点为红色

224                      * 把兄弟节点染红,兄弟的左子节点染黑

225                      * 以兄弟节点为支点左旋

226                      */

227                     if (sibling.left.color == 'B') {

228                         sibling.color = 'R';

229                         sibling.right.color = 'B';

230                         leftRotate(sibling);

231                         sibling = node.parent.left;

232                     }

233                     

234                     /*

235                      * 当前结点和兄弟节点为黑色,兄弟的右子节点为黑色

236                      * 将兄弟节点染成当前结点的父节点的颜色

237                      * 当前节点的父节点染黑

238                      * 以当前结点的父节点为支点进行右旋

239                      */

240                     sibling.color = node.parent.color;

241                     node.parent.color = 'B';

242                     sibling.left.color = 'B';

243                     rightRotate(node.parent);

244                     node = root;

245                 }

246             }

247         }

248         node.color = 'B';

249     }

250     

251     /*

252      * 删除节点

253      * 只会在只有一个子节点的节点上进行

254      */

255     public void delete(int key)

256     {

257         Node node = search(key, root);

258         if (node == null) return;

259         

260         Node delete, child = null;

261         

262         // 如果有两个子节点则删除是其节点后继节点

263         if (node.left == null || node.right == null) {

264             delete = node;

265         }

266         else {

267             delete = interval(node);

268         }

269         

270         // 如国有子节点则判断是那个子节点

271         if (delete.left != null || delete.right != null) {

272             if (delete.left != null)

273                 child = delete.left;

274             else

275                 child = delete.right;

276             

277             child.parent = delete.parent;

278         }

279         

280         // 清除删除节点的引用

281         if (delete.parent == null) {

282             root = child;

283         }

284         else {

285             if (delete == delete.parent.left)

286                 delete.parent.left = child;

287             else

288                 delete.parent.right = child;

289         }

290         

291         // 如果删除的是后继节点则将当前其值赋给当前结点

292         if (delete != node) {

293             node.key = delete.key;

294         }

295         

296         // 调整红黑树平衡

297         if (delete.color == 'B')

298             deleteFixup(child);

299     }

300     

301     private void leftRotate(Node node)

302     {

303         /*

304          * 左旋

305          *        P                  P

306          *       / \                / \

307          *      @   d              y   d

308          *     / \       -->      / \

309          *    a   y              @   c

310          *       / \            / \

311          *      b   c          a   b

312          */

313         

314         Node right = node.right;

315         node.right = right.left;

316         

317         if (node.right != null) {

318             node.right.parent = node;

319         }

320         

321         right.parent = node.parent;

322         if (right.parent == null) {

323             root = right;

324         }

325         else {

326             if (node == node.parent.left)

327                 node.parent.left = right;

328             else

329                 node.parent.right = right;

330         }

331         

332         right.left = node;

333         node.parent = right;

334     }    

335     

336     private void rightRotate(Node node)

337     {

338         /*

339          * 右旋

340          *        P                P

341          *       / \              / \

342          *      d   @            d   y

343          *         / \    -->       / \

344          *        y   a            b   @        

345          *       / \                  / \

346          *      b   c                c   a

347          */

348         

349         Node left = node.left;

350         node.left = left.right;

351         

352         if (node.left != null) {

353             node.left.parent = node;

354         }

355         

356         left.parent = node.parent;

357         if (left.parent == null) {

358             root = left;

359         }

360         else {

361             if (node == node.parent.left) 

362                 node.parent.left = left;

363             else 

364                 node.parent.right = left;

365         }

366         

367         left.right = node;

368         node.parent = left;

369     }

370 

371     /*

372      * 最小值想做遍历寻找

373      */

374     private Node min(Node node)

375     {

376         while (node.left != null) {

377             node = node.left;

378         }

379         return node;

380     }

381     

382     /*

383      * 最大值向右遍历寻找

384      */

385     private Node max(Node node)

386     {

387         while (node.right != null) {

388             node = node.right;

389         }

390         return node;

391     }

392     

393     /*

394      * 查找直接后继节点

395      */

396     private Node interval(Node node)

397     {

398         /*

399          * 如果有右子节点则在右子节点中寻找

400          * 否则查找父节点为左子节点的节点作为后继节点

401          */

402         if (node.right != null)

403             return min(node.right);

404         else {

405             Node parent = node.parent;

406             while (parent != null && node == parent.right) {

407                 node = parent;

408                 parent = node.parent;

409             }

410             return parent;

411         }

412     }

413     

414     /*

415      * 比较大小

416      */

417     private int compare(int a, int b)

418     {

419         return a > b ? 1 : a < b ? -1 : 0;

420     }

421 

422     /*

423      * 前序遍历

424      */

425     public void preOrder()

426     {

427         preOrder(root);

428     }

429     

430     private void preOrder(Node node)

431     {

432         if (node == null) return;

433         

434         System.out.println(node.key + " " + node.color);

435         preOrder(node.left);

436         preOrder(node.right);

437     }

438     

439     /*

440      * 后续遍历

441      */

442     public void postOrder()

443     {

444         postOrder(root);

445     }

446     

447     private void postOrder(Node node)

448     {

449         if (node == null) return;

450         

451         postOrder(node.left);

452         postOrder(node.right);

453         System.out.println(node.key + " " + node.color);

454     }

455     

456     /*

457      * 中序遍历

458      */

459     public void inOrder()

460     {

461         inOrder(root);

462     }

463     

464     private void inOrder(Node node)

465     {

466         if (node == null) return;

467         

468         inOrder(node.left);

469         System.out.println(node.key + " " + node.color);

470         inOrder(node.right);

471     }

472     

473     static class Node

474     {

475         Node parent;

476         Node left;

477         Node right;

478         char color = 'B';

479         int key;

480         

481         public Node(int key)

482         {

483             this.key = key;

484         }

485         

486         public Node(char color)

487         {

488             this.color = color;

489             this.key = -Integer.MIN_VALUE;

490         }

491     }

492     

493     public static void main(String[] args)

494     {

495         int[] array = new int[20];

496         

497         Random rond = new Random();

498         for (int i = 0; i < array.length; i++) {

499             array[i] = Math.abs(rond.nextInt()) % 40;

500         }

501         

502         RBTree tree = new RBTree(array);

503         //tree.preOrder();

504         tree.inOrder();

505         

506         System.out.println();

507         System.out.println("delete " + array[6]);

508         System.out.println();

509         

510         tree.delete(array[6]);

511         //tree.preOrder();

512         tree.inOrder();

513     }

514 }

你可能感兴趣的:(红黑树)