I am struggling to implement a method called find_set within my class blob. It is a recursive function which returns pointer to a blob object. My blob class is basically a linked list and this function is supposed to be passed a blob and then recursively traverse blob's parents until arriving at the head of the blob list.
I am at work so I am having to recreate the essentially components. This is not copy and pasted version of my code, but I want to know how to do it by the time I get home.
class blob{
public:
int size;
int index[2];
char value;
blob *parent;
blob *find_set(blob* &in_question);
};
The necessary elements of the blob class to understand my conundrum.
blob* blob::find_set(blob* &in_question){
if(in_question!=nullptr)
in_question.parent= find_set(&in_question.parent);
return in_question;
}
I hope I have been explicit enough.
So, I'm guessing the problem is here:
blob* blob::find_set(blob* &in_question){
if(in_question!=nullptr)
in_question.parent= find_set(&in_question.parent);
return in_question;
}
I'm not quite sure why you're taking a reference to a pointer, but here's a working version of the code:
blob* blob::find_set(blob* in_question){
if(in_question != nullptr)
in_question->parent = find_set(in_question->parent);
return in_question;
}
Accessing members of a pointer requires using -> instead of .
Taking the address of in_question->parent yields an object of type blob**, which is probably not what you want
If the purpose of the method is to get the "top blob", i.e. the blob that has no parent, I would change the name to get_top_blob or similar.
Naming aside, you need to change the recursion termination condition so that the last recursion call actually returns the "top blob" (currently, the last call returns nullptr).
blob* blob::get_top_blob(blob* in_question){
if(in_question == nullptr) //no blob -> no "top blob"
return nullptr;
else if(in_question->parent != nullptr) // get the "top blob" of the parent
return get_top_blob(in_question->parent);
else //in_question is the "top blob"
return in_question;
}
Update:
Or, in case you wish to "flatten" the tree at the same time (see the Enhancements section
in Disjoint set data structure (C). They're not using recursion and thus their code is easier to read IMO. And now that you have clarified the context, their naming is probably better than what I suggested)
blob* blob::get_top_blob(blob* in_question){
if(in_question == nullptr) //no blob -> no "top blob"
return nullptr;
else if(in_question->parent != nullptr) // get the "top blob" of the parent
{
top_blob = get_top_blob(in_question->parent);
in_question->parent = top_blob;
return top_blob;
}
else //in_question is the "top blob"
return in_question;
}
This is what the member function find_set(...) looked like after I got it working.
blob *blob::find_set(blob &in_question){
if(in_question.parent!=nullptr)
in_question.parent= find_set(*in_question.parent);
else
std::cout<<"("<<in_question.index[0]<<","<<in_question.index[1]<<")"<<std::endl;
return in_question.parent;
}
Related
void intersectionLists(LinkedList argList) {
bool common = false;
ListNode* thisCurrentPointer{headPointer};
ListNode* argCurrentPointer;
cout <<"common elements between both lists are:\n";
while(thisCurrentPointer != nullptr) {
argCurrentPointer = argList.getHeadReference();
while(argCurrentPointer != nullptr){
if(thisCurrentPointer->data == argCurrentPointer->data) {
cout <<thisCurrentPointer->data;
common = true;
break;
}
argCurrentPointer = argCurrentPointer->nextPointer;
}
thisCurrentPointer = thisCurrentPointer->nextPointer;
}
if(!common) {
cout <<"none\n";
}
thisCurrentPointer = nullptr;
argCurrentPointer = nullptr;
delete thisCurrentPointer;
delete argCurrentPointer;
}
Hello everyone,
Iwas making this function for intersection in the linkedList class, which has the parameter of another linkedList object, one utility function i am using on line 9 is getHeadReference(), which simply returns the address stored in the headPointer (i am using this function in order to get argCurrentPointer to point at the head of the list that came in the parameter).
Anyway.. the function gives perfectly fine output of whatever two linked lists are but the control get "stuck" right after its execution, the control freezes, and a huge garbage value is returned, i really hope i am being clear.
I have dry run the code i can not seem to find the problem. Even in main when i call another function after the execution of "intersectionLists" function, the called function gets executed properly without any delay but the control can't seem to exit main after all the work is done, when i don't call this intersection code, no hang or delay whatsoever is observed, please help. Thank you.
I think this is because you detele thisCurrentPointer and argCurrentPointer after setting them to null. It is not necessary to do any deletion after as you are not duplicating your nodes.
I am writing a method to Delete duplicate-value nodes from a sorted linked list in c++. I'm trying to use Node* instead of void return type but facing an error because of the return statement.
My method code..
Node* RemoveDuplicates(Node *head)
{
struct Node* current = head;
struct Node* next_next;
if(current == NULL)
return;
while(current->next != NULL)
{
if(current->data == current->next->data)
{
next_next = current->next->next;
free(current->next);
current->next = next_next;
}
else
{
current = current->next;
}
}
}
The compile time error message i am receiving..
solution.cc: In function 'Node* RemoveDuplicates(Node*)':
solution.cc:31:6: error: return-statement with no value, in function returning 'Node*' [-fpermissive]
return ;
^
Change the return type to void.
There is nothing valuable to be returned from the function.
The compiler doesn't pretend to know what you are thinking, he asks you to make contracts on what is going on. Hence, declaring the return type Node* you must provide an output of that specific type : a Node pointer. The most likely scenario I can imagine here would be returning the current node without the duplicates at the end of the function.
Node* RemoveDuplicates(Node *head)
{
// some instructions
return head;
}
so you can have this kind of semantic :
Node* distinctList = RemoveDuplicates(head);
if (distinctList) // NULL (0 / false) if empty
{
// some more instructions
}
However, if you don't need anything to go out of the function, the return type should be void (nothing).
Hope this helps!
I will treat this as a learning exercise, and ignore the fact that it is preferable to use a std list than to implement your own linked list, and it is preferable to use new and delete to using malloc and free.
If you specify Node* as a return type, you must return a pointer to a node. In order to answer your question, you have to ask is: what pointer do you want to return? As written you are deleting all duplicate pointers. Do you want to return the last pointer deleted? Do you want to loop until you find a duplicate and delete that?
You have two exit points in your code snippet. The first is a plain "return" statement, which is called when the list is empty. As written you are returning void, i.e. nothing. You need to return a pointer to a Node, but you have no valid pointers, so you probably want to return a null_ptr, which is a pointer to nothing.
Now we come to the part of your question which depends on the desired behavior. For example:
while(current->next != NULL)
{
if(current->data == current->next->data)
{
next_next = current->next->next;
free(current->next);
current->next = next_next;
/// Here you have a valid pointer you could return:
return current;
}
else
{
current = current->next;
}
// if you get here, no duplicates were found, so you can return a nullptr.
return std::nullptr;
}
Will loop over your list until a duplicate is found, will delete that duplicate, and return a pointer to the remaining pointer. If no duplicates are found, a nullptr is returned.
I leave it as an exersize to modify this to loop over all elements in the list until the last duplicate is found (hint, you will have to introduce a local variable to store the return value), and return that.
Good luck.
I'm a beginner programmer(Just started) and I'm writing some code for a binary search tree for fun.
For some reason, whenever I call this append function my program crashes. It has to do with one of the two functions itself, not anything else in the header file or my source file which includes main(). By the way Leaf is just a struct with an int value, and two Leaf pointers named left and right.
This crashes with no output error.
Leaf* BinarySearchTree::GetLeaf(int x,Leaf*a)
{
int key = a->value;
cout <<key<<"\n";
if(x > key)
{
if(a->right == NULL)
{
Leaf* newleaf = new Leaf();
newleaf->value = x;
a->right = newleaf;
return newleaf;
}
else if (a->right != NULL)
{
return a->right;
}
}
else if(x< key)
{
if(a->left == NULL)
{
Leaf* newleaf = new Leaf();
newleaf->value = x;
a->left = newleaf;
return newleaf;
}
else if (a->left != NULL)
{
return a->left;
}
}
else if(x == key)
{
//tbc
}
}
void BinarySearchTree::Append(int x)
{
if(root != NULL)
{
Leaf* current = root;
while(current->value != x)
{
current = BinarySearchTree::GetLeaf(x,current);
cout<<"value: "<<
current->value;
}
}
else
{
cout <<" No ROOT!";return;
}
}
If you want to see my main (source) file, go here(Since I don't want to flood this post)
http://pastebin.com/vrh7KkMm
If you want to see the rest of the header file, where these two functions are located,
http://pastebin.com/ZGWewPdV
In your BinarySearchTree constuctor, you start accessing root without having allocated memory for it first. This may be your crash. Try adding
root = new Leaf()
at the start of the constructor.
Edit - More information:
C++ does not automatically set values for your member variables, you normally need to initialize them by hand. (c++11 does allow you to do it in the declaration). This means that any variable that you don't set to a value will have a garbage value in it. If you use this garbage value as a pointer, you will most likely get a crash.
In your case, one of the initial problems is that the LinkedList class did not initialize its root member variable in the constructor before starting to reference it.
BinarySearchTree has the same problem.
Learning to use the debugger is one of the best things you can do when learning to program. It lets you step through your code one line at a time and look at the value of each variable. This makes i easy to see where things aren't going as you planned. Which debugger you use depends on your platform.
If GetLeaf() is called with x == key the function returns neither nullptr nor a valid pointer. This is a potential crash source. You need to return something sensible in any case.
UPDATE: Don't forget to initialize the Leaf structure properly in its constructor (all three members).
UPDATE2: Also initialize your root properly. I would initialize it with nullptr and change the append function in a way that it creates the very first leave if root==nullptr.
template <typename Type>
bool Lazy_deletion_node<Type>::insert( Type const &obj ) {
if(this == nullptr){
Lazy_deletion_node<Type> *tmp = new Lazy_deletion_node( obj );
this = tmp;
return true;
}
else if(obj == this->retrieve()){
if(erased){
erased = false;
return true;
}
else{
return false;
}
}
else if(obj < this->retrieve()){
left()->insert( obj );
}
else if(obj > this->retrieve()){
right()->insert( obj );
}
}
Hey guys, I'm trying to to do an insert for a Lazy deletion tree, which is basically a binary search tree except that I mark the nodes as "erased" instead of actually removing them from the tree. This is a method to insert a new node into the tree containing the object obj. nullptr is defined to be 0.
I first test to see if the pointer is pointing to 0. If it is, I create a node that stores obj inside and then I try to make the pointer point to this newly created node.
However, when I try to compile, it gives me the error that lvalue is required as left operand of assignment on the line that reads this = tmp;. Can anybody tell me why this is happening?
Thanks in advance.
You can't reassign this. Like the error says, it's not a modifiable l-value.
However, if this was a pointing at an object that had a mutable field of the same type you're trying to assign, you could access it through this->myField or this.myField, depending on whether it's a pointer or a reference.
"this" is a reserved keyword that is a pointer to the object currently in scope (loosely similar to "self" if you're familiar with Python). It is designed to ALWAYS point to the object currently in scope, which means you cannot change its value.
What you're trying to do when you use "this = tmp;" is a little bit like trying to use "false = 10;"
I am working on a binary search tree in C++ at the moment and I have reached the stage where I have to write the remove/delete function(using recursive approach, x = change(x)). I have two options:
to stop at the parent of the node of the node to be deleted;
to get to the node to delete and then call a function that will
return the parent
Approach 1: less expensive, more code
Approach 2: less code, more expensive
Which approach is better according to you, and why?
I disagree that those are your only two options.
I think a simpler solutions is to ask each node weather it should be deleted. If it decides yes then it is deleted and returns the new node that should replace it. If it decides no then it returns itself.
// pseudo code.
deleteNode(Node* node, int value)
{
if (node == NULL) return node;
if (node->value == value)
{
// This is the node I want to delete.
// So delete it and return the value of the node I want to replace it with.
// Which may involve some shifting of things around.
return doDelete(node);
}
else if (value < node->value)
{
// Not node. But try deleting the node on the left.
// whatever happens a value will be returned that
// is assigned to left and the tree will be correct.
node->left = deleteNode(node->left, value);
}
else
{
// Not node. But try deleting the node on the right.
// whatever happens a value will be returned that
// is assigned to right and the tree will be correct.
node->right = deleteNode(node->right, value);
}
// since this node is not being deleted return it.
// so it can be assigned back into the correct place.
return node;
}
The best approach would be to traverse upto the parent of the node to be deleted, and then delete that child node. Eventually using this approach you always visit the child node, since you always have to confirm the child node is the node u want to delete.
I find that the most efficient form for writing functions for tree data structures in general is the following psuedocode format.
function someActionOnTree() {
return someActionOnTree(root)
}
function someActionOnTree (Node current) {
if (current is null) {
return null
}
if (current is not the node I seek) {
//logic for picking the next node to move to
next node = ...
next node = someActionOnTree(next node)
}
else {
// do whatever you need to do with current
// i.e. give it a child, delete its memory, etc
current = ...
}
return current;
}
This recursive function recurses over the vertex set of a data structure. For every iteration of the algorithm, it either looks for a node to recurse the function on, and overwrites the data structure's reference to that node with the value of the algorithm's iteration on that node. Otherwise, it overwrites the node's value (and possibly perform a different set of logic). Finally, the function returns a reference to the parameter node, which is essential for the overwriting step.
This is a generally the most efficient form of code I've found for tree data structures in C++. The concepts apply other structures as well - you can use recursion of this form, where the return value is always a reference to a fixed point in the planar representation of your data structure (basically, always return whatever is supposed to be at the spot you're looking at).
Here's an application of this style to a binary search tree delete function to embellish my point.
function deleteNodeFromTreeWithValue( value ) {
return deleteNodeFromTree(root, value)
}
function deleteNodeFromTree(Node current, value) {
if (current is null) return null
if (current does not represent value) {
if (current is greater than my value) {
leftNode = deleteNodeFromTree(leftNode, value)
} else {
rightNode = deleteNodeFromTree(rightNode, value)
}
}
else {
free current's memory
current = null
}
return current
}
Obviously, there are many other ways to write this code, but from my experience, this has turned out to be the most effective method. Note that performance isn't really hit by overwriting pointers, since the hardware already cached the nodes. If you're looking into improving performance of your search tree, I'd recommend looking into specialized trees, like self-balancing ones (AVL trees), B-trees, red-black trees, etc.