对于我的班级,我被要求编写一个红黑树程序,该程序读取现有树然后执行插入。我已经让它在树中正确读取,前几个插入正确重组,但是在大约第二个或第三个输入之后,树的顺序与教授不匹配。我已经梳理了我的代码一千次,并与来自各地的伪代码和 C++ 实现进行了比较。我根本找不到错误。
我会很感激我能在这里得到的任何帮助。我没有要求任何人为我做作业,我已经完成了所有工作,我只是得到了一个稍微不同的输出。我已经包含了测试用例输入、教授输出和我自己的输出。我还包括了所有代码。
测试用例输入文件
8
1 11
0 2
1 1
1 7
0 5
0 8
1 14
0 15
7
4
9
300
19
321
500
18
第一行是现有树中的元素数。0 为红色 1 为黑色。树之后有一个整数(在本例中为 7),表示要插入多少个元素。
教授的输出
1 7
0 2
1 1
1 5
0 4
0 11
1 8
1 14
0 15
1 7
0 2
1 1
1 5
0 4
0 11
1 8
0 9
1 14
0 15
1 7
0 2
1 1
1 5
0 4
0 11
1 8
0 9
1 15
0 14
0 300
1 7
1 2
1 1
1 5
0 4
1 11
1 8
0 9
0 15
1 14
1 300
0 19
1 7
1 2
1 1
1 5
0 4
1 11
1 8
0 9
0 15
1 14
1 300
0 19
0 321
1 7
1 2
1 1
1 5
0 4
1 15
0 11
1 8
0 9
1 14
0 300
1 19
1 321
0 500
1 7
1 2
1 1
1 5
0 4
1 15
0 11
1 8
0 9
1 14
0 300
1 19
0 18
1 321
0 500
我的输出
1 7
0 2
1 1
1 5
0 4
0 11
1 8
1 14
0 15
1 7
0 2
1 1
1 5
0 4
0 11
1 8
0 9
1 14
0 15
1 7
1 2
1 1
1 5
0 4
1 11
1 8
0 9
0 14
1 15
0 300
1 7
1 2
1 1
1 5
0 4
1 11
1 8
0 9
0 14
1 19
0 15
0 300
1 7
1 2
1 1
1 5
0 4
1 14
0 11
1 8
0 9
0 19
1 15
1 300
0 321
1 7
1 2
1 1
1 5
0 4
1 14
0 11
1 8
0 9
0 19
1 15
1 321
0 300
0 500
1 7
1 2
1 1
1 5
0 4
1 14
0 11
1 8
0 9
0 19
1 15
0 18
1 321
0 300
0 500
生成文件
run: main.o RBnode.o RBnode.h RBTree.o RBTree.h
g++ -g3 -ggdb -O0 main.o RBnode.o RBTree.o -o RBtree
main.o: main.cpp
g++ -c main.cpp
clean:
rm -f RBtree *.o core core.*
tidy: clean
rm -f *.*~ *~
RBTree.cpp
#include <fstream>
#include<iostream>
#include<cstdio>
#include"RBTree.h"
#include<cstdlib>
// Set up tree
RBtree::RBtree(){
nil = new RBnode();
root = nil;
}
RBtree::~RBtree(){
}
// Writes pre-order tree starting at root node to file FD
void RBtree::RBwrite(RBnode* tempRoot, FILE * fd){
if(tempRoot != nil){
fprintf(fd,"%d %d\n", tempRoot->colorData, tempRoot->data);
RBwrite(tempRoot->lchild,fd);
RBwrite(tempRoot->rchild,fd);
}
}
// Returns root node of tree
RBnode* RBtree::getRoot(){
return root;
}
// Insertion for a new node
RBnode* RBtree::RBinsert(int data){
RBnode* x;
RBnode* y;
RBnode* z = new RBnode();
z->data = data;
y = this->nil;
x = this->root;
while(x != nil)
{
y = x;
if(z->data < x->data)
x = x->lchild;
else
x = x->rchild;
}
z->parent = y;
if(y == nil)
{ root = z;}
//Empty Tree
else if(z->data < y->data)
{ y->lchild = z;}
else
{ y->rchild = z;}
z->lchild = nil;
z->rchild = nil;
z->changeColor(0);
return z;
}
// Insertion of existing value from an existing tree
RBnode* RBtree::RBinsert(int color, int data){
RBnode* z = new RBnode();
z->changeColor(color);
z->changeData(data);
RBnode* x = root;
RBnode* y = nil;
while(x != nil)
{
y = x;
if(z->data < x->data)
x = x->lchild;
else
x = x->rchild;
}
z->parent = y;
if(y == nil)
root = z; //empty as Fword
else if(z->data < y->data)
{ y->lchild = z;}
else
{ y->rchild = z;}
z->lchild = nil;
z->rchild = nil;
return z;
}
// Fixup function. Based off algorithm from CLRS
void RBtree::RBinstertFixup(RBnode* z){
RBnode* y;
while(z->parent->colorData == 0 && z->parent != nil) {
if(z->parent == z->parent->parent->lchild)
{
y = z->parent->parent->rchild;
if(y->colorData == 0)
{
z->parent->changeColor(1);
y->changeColor(1);
z->parent->parent->changeColor(0);
z = z->parent->parent;
}
else
{
if(z == z->parent->rchild)
{
z = z->parent;
Lrotate(z);
}
z->parent->changeColor(1);
z->parent->parent->changeColor(0);
Rrotate(z->parent->parent);
}
}
else
{
y = z->parent->parent->lchild;
if(y->colorData == 0)
{
z->parent->changeColor(1);
y->changeColor(1);
z->parent->parent->changeColor(0);
z = z->parent->parent;
}
else
{
if(z == z->parent->lchild)
{
z = z->parent;
Rrotate(z);
}
z->parent->changeColor(1);
z->parent->parent->changeColor(0);
Lrotate(z->parent->parent);
}
}
}
root->changeColor(1);
}
// Left rotate
void RBtree::Lrotate(RBnode* x) {
RBnode* y;
y = x->rchild;
x->rchild = y->lchild;
if(y->lchild != nil)
y->lchild->parent = x;
y->parent = x->parent;
if(x->parent == nil)
root = y;
else if(x == x->parent->lchild)
x->parent->lchild = y;
else
x->parent->rchild = y;
y->lchild = x;
x->parent = y;
}
// right rotate
void RBtree::Rrotate(RBnode* x) {
RBnode* y;
y = x->lchild;
x->lchild = y->rchild;
if(y->rchild != nil)
y->rchild->parent = x;
y->parent = x->parent;
if(x->parent == nil)
root = y;
else if(x == x->parent->lchild)
x->parent->lchild = y;
else
x->parent->rchild = y;
y->rchild = x;
x->parent = y;
}
RBnode.cpp
#include<iostream>
#include"RBnode.h"
#include<cstdlib>
using namespace std;
RBnode::RBnode(){
int colorData = 1 ;
parent = NULL;
lchild = NULL;
rchild = NULL;
data = -1;
}
RBnode::~RBnode(){
}
// Assign a color to a node
void RBnode::changeColor(int color){
this->colorData = color;
}
// Assign data to a node
void RBnode::changeData( int data ){
this->data = data;
}
RBnode.h
#ifndef RBNODE_H_
#define RBNODE_H_
#include<iostream>
// create reb black node structure
class RBnode{
public:
RBnode();
~RBnode();
RBnode * parent;
RBnode * lchild;
RBnode * rchild;
int colorData;
int data;
void changeColor(int color);
void changeData(int data);
};
#endif
RBTree.h
#ifndef RBTREE_H_
#define RBTREE_H_
#include<string>
#include <list>
#include<iostream>
#include"RBnode.h"
using std::string;
using std::ifstream;
using namespace std;
// prototype functions
class RBtree{
public:
RBtree();
~RBtree();
void RBwrite(RBnode* tempRoot, FILE * fd);
RBnode* RBinsert(int);
RBnode* RBinsert(int color, int data);
void RBinstertFixup(RBnode*);
void Lrotate(RBnode* x);
void Rrotate(RBnode* x);
RBnode* getRoot();
private:
RBnode* nil;
RBnode* root;
};
#endif
主文件
#include "RBTree.h"
#include "RBnode.h"
#include <stdint.h>
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
size_t n;
uint32_t data;
RBtree* RB;
bool tree = false;
int main(int argc, char * argv[]){
//declare file pointer
FILE * fs;
FILE * fd;
// init vars here
int n,c;
RBtree* RB = new RBtree();
if (argc < 2){
printf("ERROR: include the name of the input file as an argument\n");
return 0;
}
printf("Attempting to open file %s\n", argv[1]);
char *input = argv[1];
std::ifstream inputfile;
inputfile.open(input);
if(inputfile.fail()) // Error check for file
{
std::cout << "The file could not be opened!\n";
return 0;
}else{ printf("\nFile opened succesfully!");}
//begin aquistion of data
fs = fopen(input,"r");
fd = fopen("output.txt","w");
fscanf(fs,"%d",&n);
int color, val;
// Insert existing N number of elements
for(int i = 0; i < n; i++){
fscanf(fs,"%d %d", &color, &val);
RB->RBinsert(color, val);
}
// Insert C number of elements.
fscanf(fs,"%d", &c);
int temp;
for(int i = 0; i < c; i++){
fscanf(fs,"%d",&temp);
if(temp != 0){
RB->RBinstertFixup(RB->RBinsert(temp));
RB->RBwrite(RB->getRoot(),fd);
fprintf(fd,"\n\n");
}
}
// close files and print status to console
fclose(fd);
fclose(fs);
printf("\nProgram finished!");
return 0;
}