Working on AVL implementation. When I try to perform a rotation it deletes the children of the node being rotated. So far I've only started on right. I didn't implement a parent pointer in my nodes as I used my BST as a base.
Any guesses as to why this is fracking up? If any additional info is needed I can post it. I didn't want to upload my entire class for wall-of-code reasons.
Insert
template <typename T>
void AVL<T>::insert(T data)
{
insert(mRootNode, data);
}
template <typename T>
void AVL<T>::insert(Node<T>*& node, const T &data)
{
// If the tree is empty, make a new node and make it
// the root of the tree.
if (node == NULL)
{
node = new Node<T>(data);
return;
}
// If num is already in tree: return.
if (node->mData == data)
return;
// The tree is not empty: insert the new node into the
// left or right subtree.
if (data < node->mData)
{
insert(node->mLeft, data);
}
else
{
insert(node->mRight, data);
}
// Check for balance errors
int balance = getBalance(node);
bool
rotL = (balance > 1) && (getBalance(node->mRight) == 1),
rotR = (balance < -1) && (getBalance(node->mLeft) == -1),
rotRL = (balance > 1) && (getBalance(node->mRight) == -1),
rotLR = (balance < -1) && (getBalance(node->mLeft) == 1);
if (rotR)
{
rotateRight(node);
}
}
Right Rotation
template <class T>
void AVL<T>::rotateRight(Node<T>*& node)
{
showTree(); // Show tree before rotation
Node<T>* other = node->mLeft;
Node<T>* tmp = other->mRight;
other->mRight = node;
node->mLeft = tmp;
showTree(); // Show tree after rotation
}
Balance
template <class T>
int AVL<T>::getBalance(Node<T>* node)
{
return (node->mRight ? treeHeight(node->mRight) : 0) - (node->mLeft ? treeHeight(node->mLeft) : 0);
}
Stub
void StubAVL()
{
AVL<int> tree;
cout << "Inserting: 5\n";
tree.insert(5);
cout << "Inserting: 8\n";
tree.insert(8);
cout << "Inserting: 3\n";
tree.insert(3);
cout << "Inserting: 12\n";
tree.insert(12);
cout << "Inserting: 9\n";
tree.insert(9);
cout << "Inserting: 2\n";
tree.insert(2);
cout << "Inserting: 13\n";
tree.insert(13);
cout << "Inserting: 0\n";
tree.insert(0);
cout << "Inserting: -1\n";
tree.insert(-1);
cout << "Inorder: ";
tree.showInOrder();
cout << endl;
cout << "Preorder: ";
tree.showPreOrder();
cout << endl;
cout << "Postorder: ";
tree.showPostOrder();
cout << endl;
cout << "Node Count = " << tree.nodesCount() << endl;
cout << "Leaves Count = " << tree.leavesCount() << endl;
cout << "Height = " << tree.getHeight() << endl;
cout << "The tree looks like:\n";
tree.showTree();
cout
<< "\n\n"
<< "Heights\n";
tree.showHeight();
cout
<< "\n\n"
<< "Balances\n";
tree.showBalance();
cout << "\n\n";
system("pause");
}
Output
Right after it inserts 0 ↑ the children of 3 are deleted.
Related
using namespace std;
void createsqueue();
void insertname();
void insertheight();
void del();
void push();
void display();
struct nodename
{
string name;
float height;
struct nodename *next;
};
nodename *front;
nodename *rear;
void createstack()
{
front = NULL;
rear = NULL;
}
void insertname()
{
while (true)
{
char dec;
nodename *temp;
temp = new nodename;
std::cout << "ENTER YOUR NAME : ";
std::cin >> temp -> name;
std::cout << "ENTER YOUR HEIGHT : ";
std::cin >> temp -> height;
std::cout <<'\n';
temp -> next = NULL;
if(rear == NULL)
{
rear = temp;
front = temp;
}
else
{
rear -> next = temp;
rear = temp;
}
std::cout << "ADD ANOTHER DATA? (Y/N) : ";
std::cin >> dec;
std::cout <<'\n';
if (dec == 'n' || dec == 'N')
{
break;
}
}
}
void del()
{
if(front != NULL)
{
nodename *temp = front;
cout << "The deleted element is: " << temp -> name << endl;
front = front -> next;
delete temp;
}
else
{
cout << "Queue List is empty!\n";
}
}
void display()
{
nodename *temp = front;
while(temp != NULL)
{
std::cout << "--------------------------" << '\n';
std::cout <<"NAME : "<< temp -> name << endl;
std::cout << showpoint << fixed << setprecision(0);
std::cout <<"HEIGHT : " << temp -> height << endl;
std::cout << showpoint << fixed << setprecision(2);
temp = temp -> next;
std::cout << "--------------------------" << '\n';
}
}
int main()
{
int operation;
createstack();
do
{
std::cout << "\tMAIN MENU" << endl;
std::cout << "1 - ENTER NAME : "
<< "\n2 - DELETE PREV DATA : "
<< "\n3 - DISPLAY DATA : "
<< "\n0 - End Program"
<< "\nEnter your operation: ";
cin >> operation;
switch (operation)
{
case 1: insertname();
break;
case 2: del();
break;
case 3: display();
break;
case 0: cout << "Program End";
break;
default:
cout << "Wrong option. Please insert a new operation: ";
}
}
while(operation ! = 0);
return 0;
}
This is the code.
The program Works fine the only problem I have is displaying the name with height in descending order so that the tallest person's info displays first
I have tried multiple ways but nothing seems to work it might be my in-experience in coding since im a newbie and pardon me for any error im just getting started
Modify the code for inserting a new name such that whenever you add a node,you find the correct position for it before inserting in the linked list.
void insertname(){
cin>>h;
nodename* ctr=front;
while(ctr-> height >h){
ctr=ctr->next;
}
nodename* temp =new nodename;
temp->next=ctr->next
ctr->next=temp
temp->height=h; //similarly for name
}
Just find it if the node added is the first node or any other which you have achieved and the above will add nodes in the descending order, which will be displayed as you wanted. So, you can modify it accordingly.
I am trying to construct an euler path for a rooted tree where root can have multiple children (i.e. its not a binary tree). To keep track of each already traversed child I am maintaining a queue in a map. When I encounter a root I simply pop one of its children and set it as root. The problem is whenever, I pop a child and its parent is traversed again the popped node appears again. I am guessing I need to store references of queue but can't get my head around it. Any help would be appreciated.
vector<int> getEulerPath(Node* root) {
Node* node = root;
vector<int> path;
unordered_map<int, queue<Node*>> uvc;
while(node != NULL) {
path.push_back(node->data);
cout << "processing node " << node->data << endl;
if(uvc.find(node->data) != uvc.end()) {
cout << "found queue: " << node->data << endl;
uv = uvc.find(node->data)->second;
} else {
for(int i = 0; i < node->children.size(); i++) {
uv.push(node->children[i]);
}
cout << "adding queue: " << node->data << endl;
uvc.insert(pair<int, queue<Node*>>{node->data, uv});
}
if(!uv.empty()) {
cout << "queue size before popping: " << uv.size() << endl;
cout << "have some children left for : " << node->data << endl;
node = uv.front();
uv.pop();
cout << "queue size after popping: " << uv.size() << endl;
} else {
cout << "no children left reverting back to : " << node->parent->data << endl;
node = node->parent;
}
cout << "new node is: " << node->data << endl;
}
return path;
}
Update
Following is the minimal runnable example
#include <iostream>
#include <vector>
#include <unordered_map>
#include <queue>
using namespace std;
class Node {
public:
vector<Node*> children;
Node* parent;
int data;
Node();
Node(int, Node*);
};
Node::Node() {
parent = NULL;
data = -1;
}
Node::Node(int d, Node* p) {
parent = p;
data = d;
}
Node* generateTree(vector<vector<int>> edges) {
unordered_map<int, Node*> nodes;
Node* root = new Node();
for(int i = 0; i < edges.size(); i++) {
vector<int> edge = edges[i];
Node* parent;
Node* child;
if(nodes.find(edge[0]) == nodes.end()) {
parent = new Node(edge[0], NULL);
nodes.insert(pair<int, Node*>{edge[0], parent});
} else {
parent = nodes.find(edge[0])->second;
}
if(nodes.find(edge[1]) == nodes.end()) {
child = new Node(edge[1], parent);
nodes.insert(pair<int, Node*>{edge[0], child});
} else {
child = nodes.find(edge[1])->second;
}
if(i == 0) root = parent;
parent->children.push_back(child);
}
return root;
}
vector<int> getEulerPath(Node* root) {
Node* node = root;
vector<int> path;
unordered_map<int, queue<Node*>> uvc;
while(node != NULL) {
path.push_back(node->data);
cout << "processing node " << node->data << endl;
queue<Node*> uv;
if(uvc.find(node->data) != uvc.end()) {
cout << "found queue: " << node->data << endl;
uv = uvc.find(node->data)->second;
} else {
for(int i = 0; i < node->children.size(); i++) {
uv.push(node->children[i]);
}
cout << "adding queue: " << node->data << endl;
uvc.insert(pair<int, queue<Node*>>{node->data, uv});
}
if(!uv.empty()) {
cout << "queue size before popping: " << uv.size() << endl;
cout << "have some children left for : " << node->data << endl;
node = uv.front();
uv.pop();
cout << "queue size after popping: " << uv.size() << endl;
} else {
cout << "no children left reverting back to : " << node->parent->data << endl;
node = node->parent;
}
cout << "new node is: " << node->data << endl;
}
return path;
}
int main() {
vector<vector<int>> edges;
edges.push_back(vector<int> {1, 2});
edges.push_back(vector<int> {1, 3});
edges.push_back(vector<int> {1, 4});
edges.push_back(vector<int> {3, 5});
edges.push_back(vector<int> {3, 6});
edges.push_back(vector<int> {3, 7});
Node* root = generateTree(edges);
vector<int> euler_path = getEulerPath(root);
for(int i = 0; i < euler_path.size(); i++) {
cout << euler_path[i] << " ";
}
cout << endl;
return 0;
}
This is what I have so far, but it's not working. Basically skips to else if(cnode == preposition).
void LinkedList::Delete(Node *PrePosition) {
Node *cnode = head;
Node *pnode = NULL;
while (cnode != NULL) {
if (cnode->value != NULL) {
if (pnode == NULL) {
// if there is not previous node
head = cnode->next;
}
else if (cnode == PrePosition) {
// if there is previous node
cout << endl << "Deleting: " << cnode << endl;
pnode->next = cnode->next;
}
}
else {
// don't delete
pnode = cnode;
}
cnode = cnode->next;
}
}
1: Take the pointer from the previous node and point it to the next one after the one you want to delete
2: Delete the pointer from the previous node to the current node
3: Delete the pointer from the next node to the current node (if it is a doubly-linked list)
Three cases of delete in a singly linked-list:
delete the first node
void delete_first()
{
node *temp=new node;
temp=head;
head=head->next;
delete temp;
}
delete the last node
void delete_last()
{
node *current = new node;
node *previous = new node;
current=head;
while(current->next != NULL)
{
previous = current;
current = current->next;
}
tail = previous; // if you have a Node* tail member in your LinkedList
previous->next = NULL;
delete current;
}
delete at a particular position (your case)
void LinkedList::delete_position(int pos)
{
node *current=new node;
node *previous=new node;
current=head;
for(int i=1; i < pos; i++) //or i = 0; i < pos-1
{
previous=current;
current=current->next;
}
previous->next=current->next;
delete current;
}
^^ from codementor ^^
However if your function signature intends delete_node(Node* nodeToDelete) [PrePosition is not a good name in this case] and you want delete the node passed to the function without knowing its position in the list we can modify delete_position() like so:
void LinkedList::delete_node(Node* nodeToDelete)
{
node *current= head;
node *previous= nullptr;
if (head == nodeToDelete){
head = nodeToDelete->next;
delete nodeToDelete;
return
}//else
while(current != nodeToDelete)
{
previous = current;
current = current->next
}
previous->next = current->next;
delete nodeToDelete;
}
Also in your original code, if it's skipping the line you mentioned, pnode is always null when cnode has a non-null value in it.
Here are the full code
class SportShoe {
private:
struct nodeSport {
int ShoeID;
char BrandShoe[SIZE];
char TypeShoe[SIZE];
char ColourShoe[SIZE];
int SizeShoe;
float PriceShoe;
nodeSport *last;
};
nodeSport *first = NULL;
public:
int MenuSportShoe();
void AddSportShoe();
void DisplaySportShoe();
void DeleteSportShoe();
static void ExitSportShoe();
};
int SportShoe::MenuSportShoe() {
int OptionSportShoe = 0;
cout << endl;
cout << "Please select from the menu:" << endl;
cout << ":: 1 :: Add item to shoe list" << endl;
cout << ":: 2 :: Display shoes list" << endl;
cout << ":: 3 :: Delete item from the list" << endl;
cout << ":: 4 :: Back" << endl;
cout << "=>> ";
cin >> OptionSportShoe;
while (OptionSportShoe == 1){
AddSportShoe();
}
while (OptionSportShoe == 2){
DisplaySportShoe();
}
while (OptionSportShoe == 3){
DeleteSportShoe();
}
while (OptionSportShoe == 4){
ExitSportShoe();
}
return 0;
}
void SportShoe::AddSportShoe() {
nodeSport *tempShoe1, *tempShoe2;
tempShoe1 = new nodeSport;
cout << "Please enter the Shoe ID : (eg. 43210) " << endl;
cout << "=>> ";
cin >> tempShoe1->ShoeID;
cout << "Please enter the Shoe Brand: (eg. Adidas) " << endl;
cout << "=>> ";
cin.sync();
cin.getline(tempShoe1->BrandShoe,SIZE);
cout << "Please enter the Shoe Type : (eg. Running) " << endl;
cout << "=>> ";
cin.sync();
cin.getline(tempShoe1->TypeShoe,SIZE);
cout << "What is the Shoe Colour : (eg. Grey) " << endl;
cout << "=>> ";
cin.sync();
cin.getline(tempShoe1->ColourShoe,SIZE);
cout << "Please enter Shoe Size : (eg. 9) " << endl;
cout << "=>> ";
cin >> tempShoe1->SizeShoe;
cout << "Please enter the price of the Shoe : (eg. RM123.45) " << endl;
cout << "=>> RM ";
cin >> tempShoe1->PriceShoe;
tempShoe1->last = NULL;
if (first == NULL)
first = tempShoe1;
else
{
tempShoe2 = first;
while (tempShoe2->last != NULL)
tempShoe2 = tempShoe2->last;
tempShoe2->last = tempShoe1;
}
system("PAUSE");
MenuSportShoe();
}
void SportShoe::DisplaySportShoe() {
nodeSport *tempShoe1;
tempShoe1 = first;
while(tempShoe1){
cout << "ID : " << tempShoe1->ShoeID << endl;
cout << "Brand : " << tempShoe1->BrandShoe << endl;
cout << "Type : " << tempShoe1->TypeShoe << endl;
cout << "Colour : " << tempShoe1->ColourShoe << endl;
cout << "Size : " << tempShoe1->SizeShoe << endl;
cout << "Price : " << tempShoe1->PriceShoe << endl;
cout << endl;
tempShoe1 = tempShoe1->last;
}
system("PAUSE");
MenuSportShoe();
}
void SportShoe::DeleteSportShoe(){
nodeSport *tempShoe1, *tempShoe2;
int DataShoe;
tempShoe2 = tempShoe1 = first;
if(tempShoe1 == NULL)
{
cout << "\nList is empty!" << endl;
system("PAUSE");
MenuSportShoe();
}
while(tempShoe1 != NULL)
{
cout << "\nEnter the Shoes ID to be deleted: (eg. 123) ";
cin >> DataShoe;
tempShoe2 = tempShoe1;
tempShoe1 = tempShoe1->last;
if(DataShoe == tempShoe1-> ShoeID){
if(tempShoe1 == first) {
first = first->last;
cout << "\nData deleted ";
}
else{
tempShoe2->last = tempShoe1->last;
if(tempShoe1->last == NULL){
tempShoe2 = tempShoe2;
}
cout << "\nData deleted ";
}
delete(tempShoe1);
system("PAUSE");
MenuSportShoe();
}
else{
cout << "\nRecord not Found!!!" << endl;
system("PAUSE");
MenuSportShoe();
}
}
}
void SportShoe::ExitSportShoe(){
int sepatu;
cout << endl;
cout << "Please choose the option below."<<endl;
cout << ":: 1 :: Sport Shoe." << endl;
cout << ":: 2 :: Ladies High Heel." << endl;
cout << ":: 3 :: Exit" << endl;
cout << "=>> ";
cin >> sepatu;
while(sepatu == 1){
SportShoe listShoe;
listShoe.MenuSportShoe();
}
while(sepatu == 2){
HighHeel listShoe;
listShoe.MenuHighHeel();
}
while(sepatu == 3){
cout << "Thank you. Till we meet again."<< endl;
exit(1);
}
}
main() {
cout << "Hello! Welcome to MySepatu Online Shop administrator."<< endl;
cout << endl;
SportShoe::ExitSportShoe();
HighHeel::ExitHighHeel();
return 0;
}
public class linkedList {
int count = 0;
class Node {
int element;
Node next;
Node(int element) {
this.element = element;
}
}
Node head = null;
Node tail = null;
public void addNode(int Object) {
Node newNode = new Node(Object);
if (head == null) {
head = tail = newNode;
} else {
tail.next = newNode;
tail = newNode;
}
}
public void Display() {
Node current = head;
while (current!=null) {
System.out.println(current.element);
count ++;
current = current.next;
}
}
public void Length() {
System.out.println(count);
}
public void Remove(int node) {
Node curr = head;
while (curr!=null) { // looping the nodes
if (curr.element == node ) {
curr.element = curr.next.element;
curr = curr.next;
// To fix the Duplicates
while (curr!= tail) {
curr.element = curr.next.element;
curr = curr.next;
}
RemoveEnd();
break;
}
curr = curr.next;
}
}
public void RemoveEnd() {
Node current3 = head;
while (current3.next != tail) {
current3 = current3.next;
}
tail = current3;
tail.next = null;
}
}
I am really trying to figure out the bug in my code I wrote for AVL tree but there seems to be a bug in it.
It calls the rotation functions but when it finishes rotation there are several problem:
root doesn't change
only root value is displayed when in-order traversal is done, other values seem to disappear
I have been trying to fix this bug since 2-3 days but cant seem to solve it.
Would love some help from you guys. I will be attaching the code with this.
/*
insertion
rotations all DONE
level order DONE
deletion
*/
#include <iostream>
#include <queue>
using namespace std;
struct node
{
int data;
int height;
node *left;
node *right;
node()
{
height = 0;
left = right = NULL;
}
};
class AVL
{
public:
node *root;
AVL()
{
root = NULL;
}
// search function
bool search(int num)
{
node *nodePtr = root;
if (root->data == num)
{
cout << "FOUND " << endl;
return true;
}
else
{
while (nodePtr != NULL)
{
if (nodePtr->data < num)
{
nodePtr = nodePtr->right;
}
else if (nodePtr->data > num)
{
nodePtr = nodePtr->left;
}
else
{
cout << "FOUND " << endl;
return true;
}
}
cout << "NOT FOUND " << endl;
return false;
}
}
// inorder
void inorder()
{
inorder(root);
}
// postorder
void postorder()
{
postorder(root);
}
// preorder
void preorder()
{
preorder(root);
}
// inorder utility function
void inorder(node *&nodePtr)
{
if (nodePtr)
{
inorder(nodePtr->left);
cout << nodePtr->data << ", ";
inorder(nodePtr->right);
}
}
// preorder utility function
void preorder(node *&nodePtr)
{
if (nodePtr)
{
cout << nodePtr->data << ", ";
preorder(nodePtr->left);
preorder(nodePtr->right);
}
}
// postorder utility function
void postorder(node *&nodePtr)
{
if (nodePtr)
{
postorder(nodePtr->left);
postorder(nodePtr->right);
cout << nodePtr->data << ", ";
}
}
// returns the number of nodes in the tree
int size(node *&nodePtr)
{
if (!nodePtr)
{
return 0;
}
else
{
return (size(nodePtr->left) + size(nodePtr->right)) + 1;
}
}
// function to check if tree is empty or not
bool isempty()
{
if (root == NULL)
{
return true;
}
else
{
return false;
}
}
// max function to calculate height and also the balance factor
int maximum(int x, int y)
{
if (x>y)
{
return x;
}
else
{
return y;
}
}
// returns the level of the tree
int returnHeight(node *&nodePtr)
{
if (nodePtr == NULL)
{
return 0;
}
else
{
return nodePtr->height;
}
}
// assigning the height to the node
void assignHeightToNode(node *&nodePtr)
{
int left = returnHeight(nodePtr->left);
int right = returnHeight(nodePtr->right);
nodePtr->height = maximum(left, right) + 1;
}
// single left rotate
node *singleLeftRotate(node *&nodePtr)
{
// if (nodePtr==NULL)
// {
// return;
// }
node * b = nodePtr->right;
nodePtr->right = b->left;
b->left = nodePtr;
return b;
}
// single right rotate
node *singleRightRotate(node *&nodePtr)
{
// if (nodePtr==NULL)
// {
// return ;
// }
node * b = nodePtr->left;
nodePtr->left = b->right;
b->right = nodePtr;
assignHeightToNode(nodePtr);
assignHeightToNode(b);
return b;
}
// double left rotate
node *doubleLeft(node *&nodePtr)
{
nodePtr->right = singleRightRotate(nodePtr->right);
return singleLeftRotate(nodePtr);
}
// double right rotate
node *doubleRight(node *&nodePtr)
{
nodePtr->left = singleLeftRotate(nodePtr->left);
return singleRightRotate(nodePtr);
}
// insert function
void insert1(int x)
{
cout << "NOW INSERTING " << x << endl;
insert2(x, root);
}
// insert utility function
void insert2(int &x, node *&nodePtr)
{
if (nodePtr == NULL)
{
node *newNode = new node;
newNode->data = x;
newNode->height = 0;
nodePtr = newNode;
checkRotations(nodePtr, x);
return;
}
else
{
if (x < nodePtr->data)
{
cout << endl << "GOING LEFT " << endl;
insert2(x, nodePtr->left);
}
else if (x > nodePtr->data)
{
cout << endl << "GOING RIGHT " << endl;
insert2(x, nodePtr->right);
}
else if (nodePtr->data == x)
{
cout << "DUPLICATE VALUES NOT ALLOWED " << endl;
return;
}
}
checkRotations(nodePtr, x);
}
// checking if rotations needed
void checkRotations(node *&nodePtr, int &x)
{
assignHeightToNode(nodePtr);
cout << endl << endl << "HEIGHT OF " << nodePtr->data << " IS " << nodePtr->height << endl;
int bf = returnHeight(nodePtr->left) - returnHeight(nodePtr->right);
cout << endl << endl << "BALANCE FACTOR AT NODE " << nodePtr->data << " IS " << bf << endl;
if (bf < -1 || bf > 1)
{
cout << endl << endl << "ROTATION IS HAPPEENING " << endl << endl;
if (x > nodePtr->data)
{
singleLeftRotate(nodePtr);
cout << endl << "ROTATION DONE SINGLE LEFT " << endl;
return;
}
else if (x < nodePtr->data)
{
singleRightRotate(nodePtr);
cout << endl << "ROTATION DONE SINGLE RIGHT " << endl;
return;
}
else if (x < root->data && x > root->left->data)
{
doubleRight(nodePtr);
cout << endl << "ROTATION DONE DOUBLE LEFT " << endl;
return;
}
else if (x > root->data && x < root->right->data)
{
doubleLeft(nodePtr);
cout << endl << "ROTATION DONE DOUBLE LEFT " << endl;
return;
}
}
}
// level order display code
void levelOrderDisplay()
{
levelOrderDisplay2(root);
}
// level order display utility function
void levelOrderDisplay2(node *&nodePtr)
{
if (nodePtr == NULL)
{
cout << "THE TREE IS EMPTY" << endl;
return;
}
queue <node *> displayer;
displayer.push(nodePtr);
while (!displayer.empty())
{
node *currentNode = displayer.front();
cout << currentNode->data << ", ";
if (currentNode->left != NULL)
{
displayer.push(currentNode->left);
}
else if (currentNode->right != NULL)
{
displayer.push(currentNode->right);
}
displayer.pop();
}
}
void rootD()
{
cout << "root is " << root->data << endl;
}
};
int main()
{
AVL tree;
tree.insert1(3);
tree.insert1(2);
tree.insert1(1);
tree.insert1(4);
tree.insert1(5);
tree.insert1(6);
tree.insert1(7);
tree.inorder();
// tree.rootD();
// tree.levelOrderDisplay();
// tree.rootD();
return 0;
}
I suggest you that do not pass node pointer by reference where your code does not change pointer value such as print. Try this... I completed my avl tree code just 2 3 day before and i have similar problem, when i debug my program i came to know that somehow in print function my pointer value is changed because i passed it by reference..... So.. Try this and see if work or not.... Hope this might help you.
Really late answer, but this is what you had to do. You should set the node passed in the function equal to the temporary node made in the function. In coding language, nodePtr=b should have been the last line of the single rotate functions.
Hope this helps :)
Suppose we have a singly linked list of integers and we are given the following requirements:
For a given node, menu option 1 should display the data field of the node and any subsequent nodes in the console output.
For a given node, menu option 2 should display the data field of the node and any subsequent nodes in the console output only if data is multiple of 2.
For a given node, menu option 3 should display the data field of the node and any subsequent nodes in the console output only if data is multiple of 3.
A possible solution is as follows:
struct node {
int data;
node *next;
};
void insertBeginning(node **list, int data)
{
node *n = new node;
n->data = data;
n->next = *list;
*list = n;
}
void option1(node *node)
{
if (node != NULL) {
cout << node->data << endl;
option1(node->next);
}
}
void option2(node *node)
{
if (node != NULL) {
if (node->data % 2 == 0)
cout << node->data << endl;
option2(node->next);
}
}
void option3(node *node)
{
if (node != NULL) {
if (node->data % 3 == 0)
cout << node->data << endl;
option3(node->next);
}
}
void main()
{
node *root = new node;
root->data = 5;
root->next = NULL;
insertBeginning(&root, 4);
insertBeginning(&root, 3);
insertBeginning(&root, 2);
insertBeginning(&root, 1);
cout << "OPTION 1" << endl;
option1(root);
cout << endl;
cout << "OPTION 2" << endl;
option2(root);
cout << endl;
cout << "OPTION 3" << endl;
option3(root);
}
But a closer inspection reveals that in each menu option there is an algorithm that loop through nodes, which is the same in all options, and then a specific action. So it might be good to separate the looping algorithm from the action. How would you do it?
In this case the looping algorithm as well as the actions are very simple, so doing a separation would be killer, but in my situation the looping algorithm and the actions are more complex, and I want to avoid copying and pasting the looping algorithm. Also, this case uses a singly linked list, but it could be a tree. Anyway I do not want to distract you with these details.
Finally consider a fourth option:
For a given node, menu option 4 should display the sum of the data field of the node and any subsequent nodes in the console output.
A possible solution is as follows:
void loopNodes(node * n, void action(node * n))
{
if (n != NULL) {
action(n);
loopNodes(n->next, action);
}
}
void option1(node * node)
{
cout << node->data << endl;
}
void option2(node * node)
{
if (node->data % 2 == 0)
cout << node->data << endl;
}
void option3(node * node)
{
if (node->data % 3 == 0)
cout << node->data << endl;
}
int sum;
void option4(node * node)
{
sum += node->data;
}
void main()
{
node *root = new node;
root->data = 5;
root->next = NULL;
insertBeginning(&root, 4);
insertBeginning(&root, 3);
insertBeginning(&root, 2);
insertBeginning(&root, 1);
cout << "OPTION 1" << endl;
loopNodes(root, option1);
cout << endl;
cout << "OPTION 2" << endl;
loopNodes(root, option2);
cout << endl;
cout << "OPTION 3" << endl;
loopNodes(root, option3);
cout << endl;
cout << "OPTION 4" << endl;
sum = 0;
loopNodes(root, option4);
cout << "SUM = " << sum << endl;
}
Option 4 introduced a challenge; the need to maintain state. I used a variable with file scope, but an alternative could be (and this is my final solution):
void loopNodes(node * n, void action(node * n, void *state), void *state)
{
if (n != NULL) {
action(n, state);
loopNodes(n->next, action, state);
}
}
void option1(node * node, void *state)
{
cout << node->data << endl;
}
void option2(node * node, void *state)
{
if (node->data % 2 == 0)
cout << node->data << endl;
}
void option3(node * node, void *state)
{
if (node->data % 3 == 0)
cout << node->data << endl;
}
void option4(node * node, void *state)
{
*(int *) state += node->data;
}
void main()
{
node *root = new node;
root->data = 5;
root->next = NULL;
insertBeginning(&root, 4);
insertBeginning(&root, 3);
insertBeginning(&root, 2);
insertBeginning(&root, 1);
cout << "OPTION 1" << endl;
loopNodes(root, option1, NULL);
cout << endl;
cout << "OPTION 2" << endl;
loopNodes(root, option2, NULL);
cout << endl;
cout << "OPTION 3" << endl;
loopNodes(root, option3, NULL);
cout << endl;
cout << "OPTION 4" << endl;
int *sum = new int;
*sum = 0;
loopNodes(root, option4, sum);
cout << "SUM = " << *sum << endl;
}
What do you think?
Any feedback is really appreciated!
Note: I have to use core language facilities (I cannot use the standard library, boost, etc.).
In terms of OOP, your option mechanism depends on some specific handling bound to each option input, which are in this case positive integers. You may consider having a Handle class which takes two inputs during construction, one is option number (i.e an integer) and second is a lambda function or a function pointer which applies the logic. Your linked list then can have a AssignHandles() method to construct the menu behavior automatically.
You could use a templated version for your loop function. This could be used with functions or function objects, which implement the operator ():
#include <iostream>
int list[] = {1, 2, 3, 4, 5};
template<class Option>
void loop(Option & option) {
for (size_t i = 0; i < sizeof(list)/sizeof(list[0]); ++i) {
option(list[i]);
}
}
void print(int e) {
std::cout << e << std::endl;
}
struct Sum {
int sum = 0;
void operator () (int e) {
sum += e;
}
};
int main(int argc, char** argv) {
loop(print);
Sum s;
loop(s);
std::cout << s.sum << std::endl;
return 0;
}