Hey I want to delete a node from my binary tree. I know a node cannot be deleted if it has both right and left children. So I have written code accordingly. But every time the program runs, it crashes.
void btdel(btree *b, char d)
{
if (b->lchild->data!=d&&b->lchild!=NULL)
btdel(b->lchild,d);
if (b->rchild->data!=d&&b->rchild!=NULL)
btdel(b->rchild,d);
if (b->lchild!=NULL&&b->lchild->data==d)
{
if (b->lchild->rchild==NULL)
b->lchild=b->lchild->lchild;
else if (b->lchild->lchild==NULL)
b->lchild=b->lchild->rchild;
else {cout<<"cannot delete"; exit(1);
}
}
else if (b->rchild!=NULL&&b->rchild->data==d)
{
if (b->rchild->rchild==NULL)
b->rchild=b->rchild->lchild;
else if (b->rchild->lchild==NULL)
b->rchild=b->rchild->rchild;
else
{cout<<"Cannot delete. "; exit(1);}
}
}
Quick look:
if (b->lchild->data!=d && b->lchild!=NULL)
should be:
if (b->lchild!=NULL && b->lchild->data!=d)
you need to check b->lchild if it has a valid address before reading its data.
Related
the printOptimalAlignment function is misbehaving. goto and return will not exit when the function reaches location (1,1)... where it should end, no crash and it stops at seemingly an arbitrary location of (6,6)... because for some reason it increments at the end of the function even though there is no increment-er for the values int yL, int xL, (but I don't follow why it calls itself if it gets to the end of the function without any "hits" on the if statements.
Full code:
https://repl.it/#fulloutfool/Edit-Distance
void printOptimalAlignment(int** arr, string y, string x,int yL, int xL){
int I_weight=1, D_weight=1, R_weight=1;
bool printinfo_allot = 1,printinfo = 1;
if(printinfo_allot){
cout<<"Location: "<<"("<<xL<<","<<yL<<")"<<"-------------------------------\n";
cout<<"Same check Letters: "<<x[xL-2]<<","
<<y[yL-2]<<"("<<(x[xL-2] == y[yL-2])<<")"<<"\n";
cout<<"LL: "<<"("<<xL-1<<","<<yL<<")"
<<":"<<arr[yL][xL-1]
<<":"<<(arr[yL][xL-1]+I_weight)
<<":"<<(arr[yL][xL])
<<":"<<(((arr[yL][xL-1]+I_weight) == arr[yL][xL])==1)
<<":"<<(yL>=1 && xL>=1)<<"\n";
cout<<"xL state:"<<((&x[xL]))<<":"<<(x[xL-1])<<"\n";
cout<<"yL state:"<<((&y[yL]))<<":"<<(y[yL-1])<<"\n";
string tx = &x[xL];
cout<<x.length()<<","<<(tx.length()+1)<<"\n";
}
string tx = &x[xL]; // slopy hotfix
if(x.length()==(tx.length()+1)){
cout<<"return functionality not working?-=-=-=-=-=-=-=-=\n";
cout<<"-> Prep last, current distance = "<<arr[yL][xL] <<"\n";
return;
//printOptimalAlignment(arr,y,x,yL-1,xL-1);
//cant use this goto... but where does it go?
//goto because_Im_a_terrible_person;
throw "how?... breaking rules... make it stop";
}
if(yL>=1 && xL>=1 && (x[xL-2] == y[yL-2]) == 1){
if(printinfo){
cout<<"-> Same (same char), current distance = "<<arr[yL][xL] <<"\n";
}
printOptimalAlignment(arr,y,x,yL-1,xL-1);
}
if(yL>=1 && xL>=1 && (arr[yL-1][xL-1] == arr[yL][xL])){
if(printinfo){
cout<<"-> Swap (same int), current distance = "<<arr[yL][xL] <<"\n";
if(arr[yL-1][xL-1]==0)cout<<"---this is last---\n";
}
printOptimalAlignment(arr,y,x,yL-1,xL-1);
}
if(yL>0 && xL>0 && (arr[yL-1][xL]+D_weight == arr[yL][xL])){
if(printinfo){
cout<<"-> Delete, current distance = "<<arr[yL][xL]<<"\n";
}
printOptimalAlignment(arr,y,x,yL-1,xL);
}
//really weird ((yL>1 && xL>1) && (((arr[yL][xL-1]+I_weight) == arr[yL][xL])==1))
//not true if it is?
bool seperate = (((arr[yL][xL-1]+I_weight) == arr[yL][xL])==1);
if(yL>=1 && xL>=1){
if((((arr[yL][xL-1]+I_weight) == arr[yL][xL])==1) && (true)){
if(printinfo){
cout<<"-> Insert, current distance = "<<arr[yL][xL]<<"\n";
cout<<"Next Location1: "<<"("<<xL-1<<","<<yL<<")"<<"\n";
}
printOptimalAlignment(arr,y,x,yL,xL-1);
return;
//how does it get here... also return gets ignored... prob another stack issue
cout<<"insert function broke?????? # (1,1) ???????????????\n";
//return;
}
}
return;
cout<<"END... Hopefully.. if you see this Something went wrong\n";
because_Im_a_terrible_person:
cout<<"QUIT\n";
}
I suspect your problem is that your function calls itself and you don't appear to be taking into account what should happen next after that call to itself finishes. So you get to your finish condition where you say the return doesn't work, but it does... it just returns to where you left off in the previous call to printOptimalAlignment, which still might do something before returning to its caller, and so on. You have three different sites where you recursively call printOptimalAlignment that aren't immediately followed by a return statement, and at any of these it might be that the code will continue and trigger another of your conditional blocks.
I'm creating a program where part of its job is to store class objects labeled Client() in a binary tree.
I create the object within a switch statement with
Client newClient = Client (first, last, iD);
transactionsTree.Insert(newClient);
The switch statement is in a loop that is reading data, so after this case is executed and the program continues, the strings within that class get set to empty "" strings. I found this out in stepping through debugging and as soon as that case block executes the strings change to empty. Any other data that gets put into that class remains but those strings will not. Even if I declare those string names in the Client.h file they are still empty after the switch case where it was created. The code where I create the newClient shown above is in a Transactions.cpp, the transactionsTree is a class object of BSTree.cpp, and there's also Client.cpp, all these classes share a connection but I'm assuming my problem has to do with how I'm inserting the objects into the binary tree.
Here is the code with the switch statement case:
case 'O': // open an account
{
string first = list.front();
list.pop();
string last = list.front();
list.pop();
stringstream getiD(list.front()); // transfer string to int
list.pop();
int iD = 0;
getiD >> iD; // transferring string to int
if (transactionsTree.Retrieve(iD)) // if Client is already in tree, prints error message
{
cout << "ERROR: Account " << iD << " is already open. Transaction refused." << endl;
}
else // else creates new Client
{
Client newClient = Client (first, last, iD);
transactionsTree.Insert(newClient);
}
break;
}
And here is my insert method for the binary tree:
void BSTree::Insert(Client &newClient)
{
if (isEmpty())
{
Node *newNode = new Node(newClient);
this->root = newNode;
}
else
add(this->root, newClient);
}
BSTree::Node* BSTree::add(Node *node, Client &newClient) // helper function for Insert()
{
if (node == nullptr)
{
Node *newNode = new Node(newClient);
return newNode;
}
if (newClient.clientID < node->pClient->clientID)
node->left = add(node->left, newClient);
else
node->right = add(node->right, newClient);
}
edit1: Upon further examination, none of the strings in the class that are declared in the header or constructor hold, although here are string vectors that hold. I also have an array of strings with the whole array declared in the header of Client.cpp but when I try and print out any strings from any Client object it only prints out an address.
edit2: I've isolated my problem to two areas, one where I try to access the Client within the tree using:
Client *ptrClient; // create pointer to access the Client once found
ptrClient = &transactionsTree.getClient(iD);
and two within my getClient method which is within my binary tree class:
Client& BSTree::getClient(int id) // returns a Client object from the tree to process() in Transactions.cpp
{
return getTheClient(this->root, id);
}
Client& BSTree::getTheClient(Node * node, int iD) // helper function for getClient that returns a Client object in the tree
{
// no need for the if condition of iD not being found because I check if the iD is in the tree before this function is executed
if (node->pClient->clientID == iD)
{
cout << node->pClient->firstName << " PRINTED HERE~~~~~~~~~~~~~" << endl;
return *node->pClient; // return client if found
}
if (iD < node->pClient->clientID)
return getTheClient(node->left, iD);
else
return getTheClient(node->right, iD);
}
Does this updated information help you help me solve my problem?
I solved my problem, it was with the two lines:
Client newClient = Client (first, last, iD);
transactionsTree.Insert(newClient);
I changed it to:
Client *newClient = new Client (first, last, iD);
transactionsTree.Insert(*newClient);
This mattered because I was creating a new object in the stack and not the heap.
I'm trying to implement the bintree, but I have problems in the insert method.
If I add the first element, the program dont crash but, when I introduce 2 or more element the program crash.
This is the code
template <typename T>
void Arbol<T>:: insertar( T c){
if(laraiz==0)
{
laraiz=new celdaArbol;
laraiz->elemento=c;
laraiz->padre=laraiz->hizqu=laraiz->hder=0;
}
else {
celdaArbol *com=laraiz;
bool poner=false;
while(poner==false){
if(c>com->elemento){
if(com->hder==0){
com->hder= new celdaArbol;
com->hder->elemento=c;
com->hder->padre=com;
poner=true;
}
else{
com=com->hder;
}
}
else {
if(com->hizqu==0){
com->hizqu= new celdaArbol;
com->hizqu->elemento=c;
com->hizqu->padre=com;
poner=true;
}
else {
com=com->hizqu;
}
}
}
}
}
I think that the problem is in the else:
else{
com=com->hizqu; //com=com->hder;
}
Because I saw in the debugger that the program enter several times in the section and should not do.
According to this code:
laraiz->padre=laraiz->hizqu=laraiz->hder=0;
You do not properly intialize pointers hizqu and hder to nullptr in constructor of celdaArbol class. And you do not initialize them in either branch of if(c>com->elemento){ so they seem to have garbage values.
Also your code can become more readable and less error prone if you use proper C++ constructions:
celdaArbol *com=laraiz;
while( true ){
celdaArbol *&ptr = c > com->elemento ? com->hder : com->hizqu;
if( ptr ) {
com = ptr;
continue;
}
ptr = new celdaArbol;
ptr->elemento=c;
ptr->padre=com;
ptr->hder = ptr->hizqu = nullptr;
break;
}
This code is logically equal to yours, except it shorter, easier to read, avoid duplication and fixes your bug.
For every leaf node (except the root of the tree), you never initialize the left child or right child node to be anything but an unspecified value.
You probably meant to initialize them as nullptr.
Here's one example:
if (com->hizqu==0){
com->hizqu = new celdaArbol;
com->hizqu->elemento = c;
com->hizqu->padre = com;
poner = true;
// What is the value of com->hizqu->hizqu?
// What is the value of com->hizqu->hder?
}
I have a class called SensorNode, which contains (among other things) a linked list of sensor objects. The node has a data member for the amount of battery power it has left, and the sensors each have a data member for how much power they draw. I have a function called processTimeClick that is supposed to go through the entire linked list of sensors in the node, and subtract the amount of power that they use from the battery that the node has left. Unfortunately I get an "Error, bad access code" and I don't know why. Here's the function I have, I was hoping someone could see where my logic is wrong.
void SensorNode::processTimeClick() {
if (batt == 0) {
}
else {
temp = mySensors;
do {
if (batt <=0) {
cout << "\nThis node has run out of battery\n";
func = 0;
break;
}
batt = (batt - (temp->SensEl->getPC()));
temp = temp->LLelement;
} while (temp->LLelement != NULL); //My code stops here and says "Thread 1:EXC_BAD_ACCESS (code=1, address=0x0)
}
}
to make it easier to understand:
temp and mySensors are both pointers (declared in the SensorNode class) of type "SensorBlock" (which is the linked list object). batt is a float data member in the SnesorNode class.
Here's the declaration for the SensorBlock class:
class SensorBlock {
friend class SensorNode;
SensorBlock * LLelement;
sensor * SensEl;
SensorBlock(sensor* senspoint);
};
SensorBlock::SensorBlock(sensor* senspoint) {
SensEl = senspoint;
LLelement = NULL;
}
Thanks for the help!
I think you want your loop to look more like this:
while (temp) {
if (batt <=0) {
cout << "\nThis node has run out of battery\n";
func = 0;
break;
}
batt = (batt - (temp->SensEl->getPC()));
temp = temp->LLelement;
}
This way, temp is checked to make sure it isn't null before you try to use it.
If you have a loop like this:
do {
// use temp
temp = temp->LLelement;
} while (temp->LLelement);
it is equivalent to
beginning_of_loop:
// use temp -- oops it might be null!
temp = temp->LLelement;
// temp might be null here
if (temp->LLelement) goto beginning_of_loop;
If you put the while at the top it is equivalent to this:
beginning_of_loop:
if (!temp) goto end_of_loop:
// use temp -- can't be null
temp = temp->LLelement;
// temp might be null here, but we aren't using it
goto beginning_of_loop;
end_of_loop:
Hello my question is why the following function fails to delete the file whose name is specified in dir1;
I use the function remove but it seems that there is some kind of a problem with it.
Please help me.
#include <stdio.h>
void test(char* dir1,char* dir2)
{
FILE * file1,* file2;
file1=fopen(dir1,"r");
file2=fopen(dir2,"w");
if(!file1){ return;}
int inpch;
char* string = new char[10];
string[9]='\0';
int br=0;
do
{
while((inpch=fgetc(file1))!=EOF)
{
string[br]=char(inpch);
br++;
if(br==9)break;
}
if(br!=9)
{
string[br]='\0';
fputs(string,file2);
return;
}
else
{
fputs(string,file2);
br=0;
}
}while(true);
fclose(file1);
remove(dir1);/// I DON"T UNDERSTAND WHY IT DOESN"T DELETE THE FILE.
fclose(file2);
}
I guess at some point before exiting the do-while loop, the following if condition becomes true, and the function returns before it reaches to the end of the function, without even calling the remove function.
if(br!=9)
{
string[br]='\0';
fputs(string,file2);
return; //<------------ here you're returning!
}
Did you want to write return or break? Looks like its there the problem lies.
Why don't you check for the return value and error code (errno) that tells you exactly why the function didn't succeed?
Replace your remove call with this :
if( remove( "myfile.txt" ) != 0 )
perror( "Error deleting file" );
else
puts( "File successfully deleted" );
and it should tell you what happened.