尝试在C中实现红黑树
我需要帮助实现一个红黑树,它似乎让seg在我的malloc调用中出错。我不知道如何修理它。如有任何建议,将不胜感激。这些函数似乎正在工作。我唯一的问题是分配内存尝试在C中实现红黑树,c,red-black-tree,C,Red Black Tree,我需要帮助实现一个红黑树,它似乎让seg在我的malloc调用中出错。我不知道如何修理它。如有任何建议,将不胜感激。这些函数似乎正在工作。我唯一的问题是分配内存 #include <stdio.h> #include <stdlib.h> typedef struct Node { int data; char color; struct Node *left; struct Node *right; struct Node *p
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
char color;
struct Node *left;
struct Node *right;
struct Node *parent;
} Node;
Node **Root = NULL;
// A utility function to create a new BST node
Node *newNode(int data) {
Node *temp = (Node*)malloc(sizeof(Node));
temp->data = data;
temp->color = 'R';
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
return temp;
}
void rotateLeft(Node **Root, Node *New) {
Node *lPtr = New->right;
New->right = lPtr->left;
if (lPtr->left != NULL)
lPtr->left->parent = New;
lPtr->parent = New->parent;
if (New->parent == NULL)
*Root = lPtr;
else if (New->data == New->parent->left->data)
New->parent->left = lPtr;
else
New->parent->right = lPtr;
lPtr->left = New;
New->parent = lPtr;
}
void rotateRight (Node**Root, Node *New) {
Node *rPtr = New->left;
New->left = rPtr->right;
if (rPtr->right != NULL)
rPtr->right->parent = New;
rPtr->parent = New->parent;
if (New->parent == NULL)
*Root = rPtr;
else if (New->data == New->parent->left->data)
New->parent->left = rPtr;
else
New->parent->right = rPtr;
rPtr->right = New;
New->parent = rPtr;
}
void redBlackInsertFixup(Node **Root, Node *New) {
Node* temp;
while (New->parent->color == 'R') {
if (New->parent->data == New->parent->parent->data) {
temp = New->parent->parent->right;
if (temp->color == 'R') {
New->parent->color = 'B';
temp->color = 'B';
New->parent->parent->color = 'R';
New = New->parent->parent;
} else
if (New->data == New->parent->right->data) {
New = New->parent;
rotateLeft(Root,New);
}
New->parent->color = 'B';
New->parent->parent->color = 'R';
rotateRight(Root, New->parent->parent);
} else {
temp = New->parent->parent->left;
if (temp->color == 'R') {
New->parent->color = 'B';
New->color = 'B';
New->parent->parent->color = 'R';
New = New->parent->parent;
} else
if (New->data == New->parent->left->data) {
New = New->parent;
rotateRight(Root, New);
}
New->parent->color = 'B';
New->parent->parent->color = 'R';
rotateLeft(Root, New->parent->parent);
}
}
Root[0]->color = 'B';
}
void redBlackInsert(Node **Root, int data) {
Node *New = (Node *)malloc(sizeof(Node));
New->data = data;
New->left = NULL;
New->right = NULL;
New->color = 'R';
Node *Yp = NULL;
Node *Xp = *Root;
if (*Root != NULL) {
New->color = 'B';
*Root = New;
return;
}
while (Xp != NULL) {
Yp = Xp;
if (data < Xp->data)
Xp = Xp->left;
Xp = Xp->right;
}
New->parent = Yp;
if (Yp == NULL) {
*Root = New;
if (data < Yp->data)
Yp->left = New;
else
Yp->right = New;
}
New->left = NULL;
New->right = NULL;
New->color = 'R';
redBlackInsertFixup(Root, New);
}
void redBlackTreePrint(Node *Root) {
Node* temp = Root;
if (temp != NULL) {
redBlackTreePrint(temp->left);
printf(" %d - %c,", temp->data, temp->color == 'B' ? 'B' : 'R');
redBlackTreePrint(temp->right);
}
return;
}
int main(int argc, char *argv[]) {
redBlackInsert(Root, 7);
redBlackInsert(Root, 9);
redBlackTreePrint(*Root);
return 0;
}
#包括
#包括
类型定义结构节点{
int数据;
炭色;
结构节点*左;
结构节点*右;
结构节点*父节点;
}节点;
节点**根=空;
//用于创建新BST节点的实用程序函数
Node*newNode(int数据){
Node*temp=(Node*)malloc(sizeof(Node));
温度->数据=数据;
温度->颜色='R';
temp->left=NULL;
temp->right=NULL;
temp->parent=NULL;
返回温度;
}
void rotateLeft(节点**根节点,节点*新建){
节点*lPtr=New->right;
新建->右侧=lPtr->左侧;
如果(lPtr->left!=NULL)
lPtr->left->parent=新建;
lPtr->parent=New->parent;
如果(新建->父项==NULL)
*根=lPtr;
else if(新建->数据==新建->父级->左侧->数据)
新建->父级->左=lPtr;
其他的
新建->父级->右=lPtr;
lPtr->左=新;
新建->父级=lPtr;
}
void rotateRight(节点**根节点,节点*新建){
节点*rPtr=New->left;
新建->左=rPtr->右;
如果(rPtr->right!=NULL)
rPtr->right->parent=新建;
rPtr->parent=新建->parent;
如果(新建->父项==NULL)
*根=rPtr;
else if(新建->数据==新建->父级->左侧->数据)
新建->父级->左=rPtr;
其他的
新建->父级->右=rPtr;
rPtr->右=新建;
新建->父级=rPtr;
}
void redBlackInsertFixup(节点**根,节点*新){
节点*温度;
而(新建->父级->颜色=='R'){
如果(新建->父级->数据==新建->父级->父级->数据){
临时=新建->父级->父级->右侧;
如果(温度->颜色=='R'){
新建->父级->颜色='B';
温度->颜色='B';
新建->父级->父级->颜色='R';
新建=新建->父级->父级;
}否则
如果(新建->数据==新建->父级->右->数据){
新建=新建->父级;
rotateLeft(根,新);
}
新建->父级->颜色='B';
新建->父级->父级->颜色='R';
rotateRight(根目录,新建->父目录->父目录);
}否则{
临时=新建->父级->父级->左侧;
如果(温度->颜色=='R'){
新建->父级->颜色='B';
新建->颜色='B';
新建->父级->父级->颜色='R';
新建=新建->父级->父级;
}否则
如果(新建->数据==新建->父级->左侧->数据){
新建=新建->父级;
rotateRight(根,新);
}
新建->父级->颜色='B';
新建->父级->父级->颜色='R';
rotateLeft(根目录,新建->父目录->父目录);
}
}
根[0]->color='B';
}
void redBlackInsert(节点**根,int数据){
Node*New=(Node*)malloc(sizeof(Node));
新建->数据=数据;
新建->左=空;
新建->右=空;
新建->颜色='R';
Node*Yp=NULL;
节点*Xp=*Root;
如果(*根!=NULL){
新建->颜色='B';
*根=新的;
返回;
}
while(Xp!=NULL){
Yp=Xp;
如果(数据数据)
Xp=Xp->左;
Xp=Xp->右;
}
新建->父级=Yp;
if(Yp==NULL){
*根=新的;
如果(数据数据)
Yp->左=新;
其他的
Yp->right=新建;
}
新建->左=空;
新建->右=空;
新建->颜色='R';
redBlackInsertFixup(根,新);
}
void redBlackTreePrint(节点*根){
节点*temp=Root;
如果(温度!=NULL){
redBlackTreePrint(临时->左侧);
printf(“%d-%c”,temp->data,temp->color=='B'?'B':'R');
redBlackTreePrint(临时->右侧);
}
返回;
}
int main(int argc,char*argv[]){
红黑插入(根,7);
红黑插入(根,9);
redBlackTreePrint(*根);
返回0;
}
谢谢 使用-g标志编译它,并使用gdb运行,您会发现它在redBlackInsert的第120行中被捕获,因为*Root为NULL
scott > gcc -O0 -g redblack.c -o redblack
scott > redblack
Segmentation fault (core dumped)
scott > gdb redblack
(gdb) run
Starting program: /home/scott/stackOverflow/redblack/redblack
Program received signal SIGSEGV, Segmentation fault.
0x000000000040098c in redBlackInsert (Root=0x0, data=7) at redblack.c:120
120 Node* Xp = *Root;
(gdb) bt
#0 0x000000000040098c in redBlackInsert (Root=0x0, data=7) at redblack.c:120
#1 0x0000000000400af5 in main (argc=1, argv=0x7fffffffded8) at redblack.c:164
(gdb)
我将全局根修改为“Node*Root”,而不是“**Root”,因为这更直观。它在main()中的三个用途必须进行修改以匹配:
int main(int argc, char* argv[])
{
redBlackInsert(&Root, 7);
redBlackInsert(&Root, 9);
redBlackTreePrint(Root);
return 0;
}
在138上,检查yp==NULL,然后取消对它的引用,这会导致139上出现分段错误:
(gdb) run
Starting program: /home/scott/stackOverflow/redblack/redblack
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400a0f in redBlackInsert (Root=0x601050 <Root>, data=7) at redblack.c:139
139 if(data < Yp->data)
(gdb) bt
#0 0x0000000000400a0f in redBlackInsert (Root=0x601050 <Root>, data=7) at redblack.c:139
#1 0x0000000000400af2 in main (argc=1, argv=0x7fffffffded8) at redblack.c:165
(gdb)
(gdb)运行
启动程序:/home/scott/stackOverflow/redblack/redblack
程序接收信号SIGSEGV,分段故障。
红黑中的0x0000000000400a0f在红黑中插入(根=0x601050,数据=7)。c:139
139如果(数据数据)
(gdb)英国电信
#红黑中的0 0x0000000000400a0f在红黑中插入(根=0x601050,数据=7)。c:139
#1 0x0000000000400af2位于红黑色处的主(argc=1,argv=0x7fffffffded8)。c:165
(gdb)
对不起,这是我的答案。这是我根据Cormen、Leiserson、Rivest、Stein的“算法简介”第13章“红黑树”提出的解决方案
#include<stdio.h>
#include<stdlib.h>
#define RED 'R'
#define BLACK 'B'
typedef struct Node{
int key;
char color;
struct Node *left;
struct Node *right;
struct Node *parent;
} Node;
// Based on CLRS algorithm, use T_Nil as a sentinel to simplify code
struct Node T_Nil_Node;
Node* T_Nil = &T_Nil_Node;
Node* Root = NULL;
// A utility function to create a new BST node
Node* newNode(int key)
{
Node *temp = (Node*) malloc(sizeof(Node));
temp->key = key;
temp->color = RED;
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
return temp;
}
void rotateLeft( Node** T, Node* x)
{
Node *y = x->right; // set y
x->right = y->left; // turn y's left subtree into x's right subtree{
if (y->left != T_Nil)
y->left->parent = x;
y->parent = x->parent; // link x's parent to y
if (x->parent == T_Nil)
*T = y;
else if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->left = x; // put x on y's left
x->parent = y;
}
void rotateRight(Node** T, Node* y)
{
Node *x = y->left; // set x
y->left = x->right; // turn x's right subtree into y's left subtree{
if (x->right != T_Nil)
x->right->parent = y;
x->parent = y->parent; // link y's parent to x
if (y->parent == T_Nil)
*T = x;
else if (y == y->parent->right)
y->parent->right = x;
else
y->parent->left = x;
x->right = y; // put y on x's right
y->parent = x;
}
void redBlackInsertFixup(Node** Root, Node* New)
{
Node* temp;
while(New->parent->color == RED)
{
if(New->parent->key == New->parent->parent->key)
{
temp = New->parent->parent->right;
if(temp->color == RED)
{
New->parent->color = BLACK;
temp->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
else if(New->key == New->parent->right->key)
{
New = New->parent;
rotateLeft(Root,New);
}
New->parent->color = BLACK;
New->parent->parent->color = RED;
rotateRight(Root,New->parent->parent);
}
else
{
temp = New->parent->parent->left;
if(temp->color == RED)
{
New->parent->color = BLACK;
New->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
else if(New->key == New->parent->left->key)
{
New = New->parent;
rotateRight(Root,New);
}
New->parent->color = BLACK;
New->parent->parent->color = RED;
rotateLeft(Root, New->parent->parent);
}
}
Root[0]->color = BLACK;
}
void redBlackInsert(Node** T, int key)
{
Node* z = newNode(key);
Node* y = T_Nil;
Node* x = *T;
// Find where to Insert new node Z into the binary search tree
while (x != T_Nil) {
y = x;
if (z->key < x->key)
x = x->left;
else
x = x->right;
}
z->parent = y;
if (y == T_Nil)
*T = z;
else if (z->key < y->key)
y->left = z;
else
y->right = z;
// Init z as a red leaf
z->left = T_Nil;
z->right = T_Nil;
z->color = RED;
// Ensure the Red-Black property is maintained
redBlackInsertFixup(T,z);
}
#define MAX(a,b) (((a)>(b))?(a):(b))
int height(Node* Root)
{
int h = 0;
if (Root != NULL) {
if (Root == T_Nil)
h = 1;
else
{
int leftHeight = height(Root->left);
int rightHeight = height(Root->right);
h = MAX(leftHeight, rightHeight) + 1;
}
}
return h;
}
int blackHeight(Node* Root)
{
int height = 0;
while (Root) {
if ((Root == T_Nil) || (Root->color == BLACK))
height++;
Root = Root->left;
}
return height;
}
void PrintHelper(Node* Root)
{
Node* temp = Root;
if (temp != NULL)
{
PrintHelper(temp->left);
printf(" %d%c(h=%d,bh=%d) ", temp->key, (temp->color == BLACK ? BLACK : RED), height(temp), blackHeight(temp));
PrintHelper(temp->right);
}
}
void redBlackTreePrint(Node* Root)
{
printf("Tree Height=%d, Black-Height=%d\n", height(Root), blackHeight(Root));
PrintHelper(Root);
printf("\n");
}
int main(int argc, char* argv[])
{
Node* Root = T_Nil;
redBlackInsert(&Root, 7);
redBlackInsert(&Root, 9);
redBlackTreePrint(Root);
}
我修改了readBlackTreePrint以显示树中每个节点的高度,以及每个节点的黑色高度(定义为指向叶子的简单路径中的黑色节点数)。代码中存在多个问题:
- 全局变量
是指向初始化为Root
的指针的指针:NULL
Node**Root=NULL代码>。这不是
所期望的:您应该传递根节点的地址,它不需要是全局变量:redBlackInsert()
int main(int argc, char *argv[]) { Node *Root = NULL; redBlackInsert(&Root, 7); redBlackInsert(&Root, 9); redBlackTreePrint(Root); return 0; }
- 您忘记在
中初始化新节点的redBlackInsert()
成员。您应该只使用parent
:newNode()
- 对
中的空树的测试不正确:redBlackInsert()
应更改为:如果(*Root!=NULL)
if (*Root == NULL) { New->color = 'B'; *Root = New; return; }
7 - B,
这是不正确的,但是
if (*Root == NULL) {
New->color = 'B';
*Root = New;
return;
}
7 - B,
#include<stdio.h>
#include<stdlib.h>
#define RED 'R'
#define BLACK 'B'
typedef struct Node {
int key;
char color;
struct Node *left;
struct Node *right;
struct Node *parent;
} Node;
// Based on CLRS algorithm, use T_Nil as a sentinel to simplify code
struct Node T_Nil_Node;
Node* T_Nil = &T_Nil_Node;
Node* Root = NULL;
// A utility function to create a new BST node
Node* newNode(int key)
{
Node *temp = (Node*) malloc(sizeof(Node));
temp->key = key;
temp->color = RED;
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
return temp;
}
void rotateLeft( Node** T, Node* x)
{
Node *y = x->right; // set y
x->right = y->left; // turn y's left subtree into x's right subtree{
if (y->left != T_Nil)
y->left->parent = x;
y->parent = x->parent; // link x's parent to y
if (x->parent == T_Nil)
*T = y;
else if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->left = x; // put x on y's left
x->parent = y;
}
void rotateRight(Node** T, Node* y)
{
Node *x = y->left; // set x
y->left = x->right; // turn x's right subtree into y's left subtree{
if (x->right != T_Nil)
x->right->parent = y;
x->parent = y->parent; // link y's parent to x
if (y->parent == T_Nil)
*T = x;
else if (y == y->parent->right)
y->parent->right = x;
else
y->parent->left = x;
x->right = y; // put y on x's right
y->parent = x;
}
void redBlackInsertFixup(Node** Root, Node* New)
{
Node* temp;
while (New->parent->color == RED)
{
if (New->parent == New->parent->parent->left)
{
temp = New->parent->parent->right;
if (temp->color == RED)
{
New->parent->color = BLACK;
temp->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
else {
if (New == New->parent->right)
{
New = New->parent;
rotateLeft(Root, New);
}
New->parent->color = BLACK;
New->parent->parent->color = RED;
rotateRight(Root, New->parent->parent);
}
}
else
{
temp = New->parent->parent->left;
if (temp->color == RED)
{
New->parent->color = BLACK;
New->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
else {
if (New == New->parent->left)
{
New = New->parent;
rotateRight(Root, New);
}
New->parent->color = BLACK;
New->parent->parent->color = RED;
rotateLeft(Root, New->parent->parent);
}
}
}
Root[0]->color = BLACK;
}
void redBlackInsert(Node** T, int key)
{
Node* z = newNode(key);
Node* y = T_Nil;
Node* x = *T;
// Find where to Insert new node Z into the binary search tree
while (x != T_Nil) {
y = x;
if (z->key < x->key)
x = x->left;
else
x = x->right;
}
z->parent = y;
if (y == T_Nil)
*T = z;
else if (z->key < y->key)
y->left = z;
else
y->right = z;
// Init z as a red leaf
z->left = T_Nil;
z->right = T_Nil;
z->color = RED;
// Ensure the Red-Black property is maintained
redBlackInsertFixup(T, z);
}
#define MAX(a,b) (((a)>(b))?(a):(b))
int height(Node* Root)
{
int h = 0;
if (Root != NULL) {
if (Root == T_Nil)
h = 1;
else
{
int leftHeight = height(Root->left);
int rightHeight = height(Root->right);
h = MAX(leftHeight, rightHeight) + 1;
}
}
return h;
}
//中序遍历
void printTree(Node* root)
{
if (root->left != T_Nil)
printTree(root->left);
printf("%d ", root->key);
if (root->right != T_Nil)
printTree(root->right);
}
int main(int argc, char* argv[])
{
Node* Root = T_Nil;
int list[10] = {1, 3, 2, 5, 4, 7, 6, 9, 8, 10};
for (int i = 0; i < 10; i++)
{
//printf("%d ", list[i]);
redBlackInsert(&Root, list[i]);
}
printTree(Root);
}
if (temp->color == RED)
{
New->parent->color = BLACK;
New->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
if (temp->color == RED)
{
New->parent->color = BLACK;
temp->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
temp->color = BLACK; // Error: New->color = BLACK;
7(B)
______|______
| |
6(R) 9(B)
___|___ ___|___
| | | |
T_NIL T_NIL 8(B) T_NIL
7(B)
______|______
| |
6(B) 9(B)
___|___ ___|___
| | | |
T_NIL T_NIL 8(R) T_NIL