Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
尝试在C中实现红黑树_C_Red Black Tree - Fatal编程技术网

尝试在C中实现红黑树

尝试在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

我需要帮助实现一个红黑树,它似乎让seg在我的malloc调用中出错。我不知道如何修理它。如有任何建议,将不胜感激。这些函数似乎正在工作。我唯一的问题是分配内存

#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