C language implementation of the Red/black tree in introduction to Algorithms

Source: Internet
Author: User
Tags textout

 

Introduction to algorithms is good, but it is a headache to read pseudocode. I always want to have a c-language version of Introduction to algorithms.

I studied the red/black tree a few days ago and translated it into C language. Compiled and tested on vc6.0. A cview class is written to show the effect.

 

Header file rb_tree.h

 

# Ifndef rb_tree_h
# Define rb_tree_h

Enum nodecolor {Red = 0, black = 1 };

Typedef int nodedata;

Struct rb_tree_node
{
Nodecolor color;
Int key;
Nodedata Info;
Rb_tree_node * left;
Rb_tree_node * right;
Rb_tree_node * parent;
};

Struct rb_tree
{
Rb_tree_node * root;
Rb_tree_node * nil;
};

Void init_rb_tree (rb_tree * t );

Void left_rotate (rb_tree * t, rb_tree_node * X );
Void right_rotate (rb_tree * t, rb_tree_node * X );

Void rb_insert (rb_tree * t, int key, nodedata info = 0 );
Void rb_insert _ (rb_tree * t, rb_tree_node * z );
Void rb_insert_fixup (rb_tree * t, rb_tree_node * z );

Void rb_delete (rb_tree * t, int key );
Void rb_delete _ (rb_tree * t, rb_tree_node * z );
Void rb_delete_fixup (rb_tree * t, rb_tree_node * X );

Int get_tree_height (rb_tree * t, rb_tree_node * X );

# Endif

 

Implementation file: rb_tree.cpp

 

/*
Implementation of the red/black tree, based on pseudo-code translation in introduction to Algorithms
Author: Hu weichen huweichen@163.com
Time: 2010.6.26
*/
# Include <stdlib. h>
// # Include <malloc. h>

# Include "rb_tree.h"

Void init_rb_tree (rb_tree * t)
{
Rb_tree_node * node = new rb_tree_node;

Node-> color = black;
Node-> info = 0;
Node-> key = 0;
Node-> left = 0;
Node-> parent = 0;
Node-> right = 0;

T-> nil = node;
T-> root = T-> nil;
}

Int get_tree_height (rb_tree * t, rb_tree_node * X)
{
Int LH = 0;
Int RH = 0;

If (X-> left! = T-> nil)
{
LH = get_tree_height (t, x-> left );
}

If (X-> right! = T-> nil)
{
RH = get_tree_height (t, x-> right );
}

If (LH> RH)
{
Return LH + 1;
}
Else
{
Return rh + 1;
}
}

Void left_rotate (rb_tree * t, rb_tree_node * X)
{
Rb_tree_node * Y = x-> right;

X-> right = Y-> left;
If (Y-> left! = T-> nil)
{
Y-> left-> parent = X;
}

Y-> parent = x-> parent;
If (X-> parent = T-> nil)
{
T-> root = y;
}
Else if (x = x-> parent-> left)
{
X-> parent-> left = y;
}
Else
{
X-> parent-> right = y;
}

Y-> left = X;
X-> parent = y;
}

Void right_rotate (rb_tree * t, rb_tree_node * X)
{
Rb_tree_node * Y = x-> left;

// Use the right child node of the left child node as the left child node
X-> left = Y-> right;
If (Y-> right! = T-> nil)
{
Y-> right-> parent = X;
}

// Replace the original left subnode with its own position.
Y-> parent = x-> parent;
If (X-> parent = T-> nil)
{
T-> root = y;
}
Else if (x = x-> parent-> right)
{
X-> parent-> right = y;
}
Else
{
X-> parent-> left = y;
}

// Use yourself as the right subnode of the original left subnode
Y-> right = X;
X-> parent = y;
}

Void rb_insert (rb_tree * t, int key, nodedata info)
{
Rb_tree_node * node = new rb_tree_node;
Node-> key = key;
Node-> info = Info;

Rb_insert _ (T, node );
}

Void rb_insert _ (rb_tree * t, rb_tree_node * z)
{
Rb_tree_node * Y = T-> nil;
Rb_tree_node * x = T-> root;

// Find a suitable Insert Location
While (X! = T-> nil)
{
Y = X;
If (Z-> key = x-> key)
{
Delete Z;
Return;
}
Else if (Z-> key <X-> key)
{
X = x-> left;
}
Else
{
X = x-> right;
}
}

// Insert a node
Z-> parent = y;
If (y = T-> nil)
{
T-> root = z;
}
Else if (Z-> key <Y-> key)
{
Y-> left = z;
}
Else
{
Y-> right = z;
}

// Assign values to other fields of the new node
Z-> left = T-> nil;
Z-> right = T-> nil;
Z-> color = Red;

// Modify the tree to meet the needs of the red/black tree
Rb_insert_fixup (T, Z );
}

Void rb_insert_fixup (rb_tree * t, rb_tree_node * z)
{
Rb_tree_node * Y = T-> nil;
 
// Loop until the parent node is black
While (Z-> parent-> color = red)
{
// If the parent node is the left child node of the grandfather Node
If (Z-> parent = z-> parent-> left)
{
Y = z-> parent-> right;
// If the uncle node is red, set both the father node and the uncle node to black and the grandfather node to red.
If (Y-> color = red)
{
Z-> parent-> color = black;
Y-> color = black;
Z-> parent-> color = Red;
Z = z-> parent;
}
// If the uncle node is black, the father node is black and the grandfather node is red,
// Then rotate right to make the grandfather node become an uncle Node
Else
{
// If it is a right sub-node, first rotate left, so that the following right rotation will be symmetric
If (Z = z-> parent-> right)
{
Z = z-> parent;
Left_rotate (T, Z );
}
Z-> parent-> color = black;
Z-> parent-> color = Red;
Right_rotate (T, Z-> parent );
}
}
// The following code is symmetric with the above Code
Else
{
Y = z-> parent-> left;
If (Y-> color = red)
{
Z-> parent-> color = black;
Y-> color = black;
Z-> parent-> color = Red;
Z = z-> parent;
}
Else
{
If (Z = z-> parent-> left)
{
Z = z-> parent;
Right_rotate (T, Z );
}
Z-> parent-> color = black;
Z-> parent-> color = Red;
Left_rotate (T, Z-> parent );
}
}
}

T-> root-> color = black;
}

Rb_tree_node * find_node (rb_tree * t, int key)
{
Rb_tree_node * x = T-> root;

While (X! = T-> nil)
{
If (Key = x-> key)
{
Return X;
}
Else if (Key <X-> key)
{
X = x-> left;
}
Else
{
X = x-> right;
}
}

Return T-> nil;
}

Void rb_delete (rb_tree * t, int key)
{
Rb_tree_node * x = find_node (T, key );
If (X! = T-> nil)
{
Rb_delete _ (t, x );
}
}

Rb_tree_node * tree_minimum (rb_tree * t, rb_tree_node * X)
{
While (X-> left! = T-> nil)
{
X = x-> left;
}

Return X;
}

Rb_tree_node * tree_successor (rb_tree * t, rb_tree_node * X)
{
Rb_tree_node * Y = T-> nil;
If (X-> right! = T-> nil)
{
Return tree_minimum (t, x-> right );
}

Y = x-> parent;
While (y! = T-> nil & X = Y-> right)
{
X = y;
Y = Y-> parent;
}

Return y;
}

Void rb_delete _ (rb_tree * t, rb_tree_node * z)
{
Rb_tree_node * Y = T-> nil;
Rb_tree_node * x = T-> nil;

// As long as Z has a byte point that is not null, Y is equal to Z; otherwise, Y is a rear drive of Z.
If (Z-> left = T-> nil | Z-> right = T-> nil)
{
Y = z;
}
Else
{
Y = tree_successor (T, Z );
}

// Set X to a subnode of Y, which may also be nil.
If (Y-> left! = T-> nil)
{
X = Y-> left;
}
Else
{
X = Y-> right;
}

// Delete y from the tree, but do not release y's memory temporarily, because it will be used later
X-> parent = Y-> parent;
If (Y-> parent = T-> nil)
{
T-> root = X;
}
Else
{
If (y = Y-> parent-> left)
{
Y-> parent-> left = X;
}
Else
{
Y-> parent-> right = X;
}
}

// If y is not equal to Z, but a rear drive of Z, copy the keyword and data of Y to Z.
If (y! = Z)
{
Z-> key = Y-> key;
Z-> info = Y-> Info;
}

// If the deleted y node is a black node, the red and black properties of the tree will be damaged, that is, the black height will change, and you need to adjust it.
If (Y-> color = black)
{
Rb_delete_fixup (t, x );
}

// In this case, the memory occupied by Y can be released.
Delete y;
}

Void rb_delete_fixup (rb_tree * t, rb_tree_node * X)
{
Rb_tree_node * w = T-> nil;

// The color of X must be adjusted only when it is black. If X is red, set it to black.
While (X! = T-> root & X-> color = black)
{
If (x = x-> parent-> left)
{
// Set w as a brother Node
W = x-> parent-> right;

// If W is red, set w to black, set w's parent node to red, and then rotate the parent node left.
If (W-> color = red)
{
W-> color = black;
X-> parent-> color = Red;
Left_rotate (t, x-> parent );
W = x-> parent-> right;
}

// If both left and right child nodes of W are black, set w to red and set X to the parent node of X,
// At this time, the black height of the left and right child nodes of the new x is the same, that is, X is a red and black tree, but the brother node of the new x
// The Black height is still large, so continue to adjust the next cycle
If (W-> left-> color = Black & W-> right-> color = black)
{
W-> color = Red;
X = x-> parent;
}
Else
{
// If the left subnode of W is red and the right subnode is black, set w to red first and black to the left subnode,
// Then rotate right to prepare for the left rotation below
If (W-> right-> color = black)
{
W-> left-> color = black;
W-> color = Red;
Right_rotate (T, W );
W = x-> parent-> right;
}

// Set w as the color of the parent node, so that the color of the New and Old parent nodes remains unchanged after the left rotation below,
// Set w's parent node and right child node to black, and then rotate left,
// In this way, the black height of the Left subnode and the right subnode is the same, so you do not need to adjust it. Therefore, set X to root.
W-> color = x-> parent-> color;
X-> parent-> color = black;
W-> right-> color = black;
Left_rotate (t, x-> parent );
X = T-> root;
}
}
// The following code is symmetric with the above Code
Else
{
W = x-> parent-> left;
If (W-> color = red)
{
W-> color = black;
X-> parent-> color = Red;
Right_rotate (t, x-> parent );
W = x-> parent-> left;
}
If (W-> right-> color = Black & W-> left-> color = black)
{
W-> color = Red;
X = x-> parent;
}
Else
{
If (W-> left-> color = black)
{
W-> right-> color = black;
W-> color = Red;
Left_rotate (T, W );
W = x-> parent-> left;
}

W-> color = x-> parent-> color;
X-> parent-> color = black;
W-> left-> color = black;
Right_rotate (t, x-> parent );
X = T-> root;
}
}
}

X-> color = black;
}

 

Ctestrbtreeview class used to display the test results

Void ctestrbtreeview: ondraw (CDC * PDC)
{
Ctestrbtreedoc * pdoc = getdocument ();
Assert_valid (pdoc );
 
If (rb_tree1.root = rb_tree1.nil)
Return;

Crect rcclient;
Getclientrect (& rcclient );
Int x = rcclient. Width ()/2;
Int y = 30;

Int level = get_tree_height (& rb_tree1, rb_tree1.root );

Drawrbtree (PDC, & rb_tree1, rb_tree1.root, level, x, y );
}

 

# Define nodedistance 24
# Define radius 20

Void ctestrbtreeview: drawrbtree (CDC * PDC, rb_tree * t, rb_tree_node * node, int level, int X, int y)
{
If (node = T-> nil)
Return;
 
Cpen pen;
Cpen penblue;
Penblue. createpen (ps_solid, 1, colorref (0xff0000 ));

If (node-> left! = T-> nil)
{
Int xleft = x-(nodedistance * (POW (2, level)-1)/4;

PDC-> SelectObject (& penblue );
PDC-> moveTo (x, y );
PDC-> lineto (xleft, Y + 60 );

Drawrbtree (PDC, T, node-> left, level-1, xleft, Y + 60 );

}

If (node-> right! = T-> nil)
{
Int xright = x + (nodedistance * (POW (2, level)-1)/4;

PDC-> SelectObject (& penblue );
PDC-> moveTo (x, y );
PDC-> lineto (xright, Y + 60 );

Drawrbtree (PDC, T, node-> right, level-1, xright, Y + 60 );
}

If (node-> color = red)
{
PDC-> settextcolor (0x0000ff );
Pen. createpen (ps_solid, 1, 0x0000ff );
}
Else
{
PDC-> settextcolor (0 );
Pen. createpen (ps_solid, 1, colorref (0 ));
}
PDC-> SelectObject (& pen );

Crect rect;
Rect. Left = x-12;
Rect. Top = Y-12;
Rect. Right = x + 12;
Rect. Bottom = Y + 12;

PDC-> ellipse (& rect );

Cstring STR;
Str. Format ("% d", node-> key );
If (node-> key <10)
{
PDC-> textout (X-4, Y-8, STR );
}
Else
{
PDC-> textout (X-8, Y-8, STR );
}
}

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.