// in this code I first created nodes stored them in a que and keep on removing them as I entered their left and right children. To make a node have no further children I entered -1 while entering data. Here I am not able to understand what is wrong with my code , I am getting wrong output for preorder and postorder traversals. It would be really great if you guys could help me out.
I made a class que for queue ds and inherited it in tree class in protected mode.
#include <iostream>
#include <math.h>
using namespace std;
struct node
{
int data;
struct node *left;
struct node *right;
};
class que
{
protected:
int start;
int end;
struct node **arr;
int n;
public:
que(int x)
{
n = x;
arr = new struct node *[n];
start = -1;
end = -1;
}
void isfull()
{
if (end == n)
cout << "Queue is full !!!" << endl;
return;
}
int isempty()
{
if (start == end)
{
start = -1;
end = -1;
cout << "Queue is empty !!!" << endl;
return 1;
}
return 0;
}
void enqu(struct node *x)
{
if (end == n)
{
cout << "called" << endl;
isfull();
return;
}
end++;
arr[end] = x;
}
struct node *dequ(void)
{
struct node *q = 0;
if (start == end)
{
isempty();
return q;
}
start++;
cout << "Element removed is ->" << arr[start] << endl;
return arr[start];
}
};
class tree : protected que
{
public:
struct node *head;
struct node *ptr;
tree(int n) : que(n)
{
head = 0;
ptr = 0;
enter();
}
void create(void)
{
ptr = new struct node;
ptr->left = 0;
ptr->right = 0;
}
void enter(void)
{
struct node *p;
if (head == 0)
{
create();
cout << "Enter root element of tree -> ";
cin >> ptr->data;
head = ptr;
cout << "Enquing ptr - " << ptr << endl;
enqu(ptr);
}
while (!isempty())
{
p = dequ();
cout << "Enter left child ->";
int x;
cin >> x;
if (x != -1)
{
create();
p->left = ptr;
ptr->data = x;
cout << "Enquing ptr - " << ptr << endl;
enqu(ptr);
}
cout << "Enter right child ->";
cin >> x;
if (x != -1)
{
create();
p->right = ptr;
ptr->data = x;
cout << "Enquing ptr - " << ptr << endl;
enqu(ptr);
}
}
}
void inorder(struct node *yes)
{
if (yes != 0)
{
inorder(yes->left);
cout << "--> " << yes->data << endl;
inorder(yes->right);
}
}
void preorder(struct node *yes)
{
if (yes != 0)
{
cout << "--> " << yes->data << endl;
inorder(yes->left);
inorder(yes->right);
}
}
void postorder(struct node *yes)
{
if (yes != 0)
{
inorder(yes->left);
inorder(yes->right);
cout << "--> " << yes->data << endl;
}
}
int count(struct node *yes)
{
static int x = 0, y = 0;
if (yes == 0)
return 0;
x = count(yes->left);
y = count(yes->right);
return x + y + 1;
}
int height(struct node *yes)
{
static int a = 0, b = 0;
if (yes == 0)
return 0;
a = count(yes->left);
b = count(yes->right);
if (a > b)
return a + 1;
else
return b + 1;
}
};
int main()
{
int x;
cout << "Enter height of tree - ";
cin >> x;
int max = 0;
max = pow(2, x + 1) - 1;
tree tr(max);
cout << "Preorder traversal -- " << endl;
tr.preorder(tr.head);
cout << "Inorder traversal -- " << endl;
tr.inorder(tr.head);
cout << "Postorder traversal -- " << endl;
tr.postorder(tr.head);
cout << "\n No. of elements -- " << tr.count(tr.head);
cout << "\n Height of tree --" << tr.height(tr.head);
}
The preorder and postorder functions doesn't call themselves recursively. Instead they call the inorder function, which will lead to all but the root will be printed using inorder.
below is my current in-progress code converting a singly linked to a doubly linked list. I haven't touched the delete function yet. I've gotten insert in empty list, end of list, and beginning of list apparently working.
However nodes inserting in the middle seemingly fail to create a link to the previous node. My debugging lines I inserted seem to show both the n->next and n-> prev with the correct memory address, but when I go to reverseprint, any nodes inserted in the middle are missed and the links are gone. Where am I going wrong in regards to this?
Code below:
#include <iostream>
#include <string>
using namespace std;
// define a node for storage and linking
class node {
public:
string name;
node *next;
node *prev;
};
class linkedList {
public:
linkedList() :top(NULL) {}
bool empty() { return top == NULL; }
node *getTop() { return top; }
node *getEnd() { return end; }
void setTop(node *n) { top = n; }
void setEnd(node *p) { end = p; }
void add(string);
int menu();
void remove(string);
~linkedList();
void reversePrint();
friend ostream& operator << (ostream&, const linkedList&); // default output is in-order print.
private:
node *top;
node *end;
};
void main() {
linkedList l;
cout << l.empty() << endl;
int option = 0;
string s;
bool go = true;
while (go) {
option = l.menu();
switch (option) {
case 1: cout << "enter a name: "; cin >> s; l.add(s); break;
case 2: cout << "enter name to be deleted: "; cin >> s; l.remove(s); break;
case 3: cout << l; break;
//case 4: cout << "can not be done with a singly linked list" << endl;
case 4: l.reversePrint(); break;
case 5: cout << "exiting" << endl; go = false; break;
}
}
system("pause");
}
void linkedList::remove(string s) {
bool found = false;
node *curr = getTop(), *prev = NULL;
while (curr != NULL) {
// match found, delete
if (curr->name == s) {
found = true;
// found at top
if (prev == NULL) {
node *temp = getTop();
setTop(curr->next);
delete(temp);
// found in list - not top
}
else {
prev->next = curr->next;
delete(curr);
}
}
// not found, advance pointers
if (!found) {
prev = curr;
curr = curr->next;
}
// found, exit loop
else curr = NULL;
}
if (found)cout << "Deleted " << s << endl;
else cout << s << " Not Found " << endl;
}
void linkedList::add(string s) {
node *n = new node();
n->name = s;
n->next = NULL;
n->prev = NULL;
// take care of empty list case
if (empty()) {
top = n;
end = n;
// take care of node belongs at beginning case
}
else if (getTop()->name > s) {
n->next = getTop();
n->prev = NULL;
setTop(n);
node *temp;
temp = n->next;
temp->prev = n;
// take care of inorder and end insert
}
else {
// insert in order case
node *curr = getTop(), *prev = curr;
while (curr != NULL) {
if (curr->name > s)break;
prev = curr;
curr = curr->next;
}
if (curr != NULL) { // search found insert point
n->next = curr;
cout << n->name << " " << n << " prev " << prev << " " << prev->name << endl;
n->prev = prev;
prev->next = n;
cout << "n->prev is: " << n->prev << " " << n->prev->name << endl;
cout << "n->next is: " << n->next << " " << n->next->name << endl;
}
// take care of end of list insertion
else if (curr == NULL) {// search did not find insert point
prev->next = n;
n->prev = prev;
cout << "n->prev is: " << n->prev << " " << n->prev->name << endl;
setEnd(n);
}
}
}
ostream& operator << (ostream& os, const linkedList& ll) {
//linkedList x = ll; // put this in and the code blows up - why?
node *n = ll.top;
if (n == NULL)cout << "List is empty." << endl;
else
while (n != NULL) {
os << n->name << endl;
os << n << endl;
if (n->next != NULL) {
os << "next is " << n->next << endl;
}
n = n->next;
}
return os;
}
void linkedList::reversePrint() {
node *n = end;
if (n == NULL)cout << "List is empty." << endl;
else
while (n != NULL) {
//cout << n->name << endl;
cout << "memory address of " << n->name << " is " << n << endl;
if (n->prev != NULL) {
cout << "prev is " << n->prev << endl;
}
n = n->prev;
}
return;
}
// return memory to heap
linkedList::~linkedList() {
cout << "~linkedList called." << endl;
node *curr = getTop(), *del;
while (curr != NULL) {
del = curr;
curr = curr->next;
delete(del);
}
}
int linkedList::menu() {
int choice = 0;
while (choice < 1 || choice > 5) {
cout << "\nEnter your choice" << endl;
cout << " 1. Add a name." << endl;
cout << " 2. Delete a name." << endl;
cout << " 3. Show list." << endl;
cout << " 4. Show reverse list. " << endl;
cout << " 5. EXIT " << endl;
cin >> choice;
}
return choice;
}
You are not setting the prev of the current in insertion into middle, just do:
n->next = curr;
curr->prev = n; // <-- this
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.
I need to find the largest element in the list. In the following code unsubscribed items and ordered them. How to find the last element of list? I think that I need add one more function void maksimum(), but I'm having trouble with that.
#include <iostream>
#include <string>
#include <time.h>
#include <conio.h>
#include <cstdlib>
using namespace std;
struct element
{
int number;
element* next;
element();
};
element::element()
{
next = NULL;
}
struct list
{
element* first;
void fill_list(int number);
void segregate();
void show_list();
void maksimum();
list();
};
list::list()
{
first = NULL;
}
void list::fill_list(int number)
{
element *nowy = new element;
nowy->number = number;
if(first == 0)
{
first = nowy;
}
else
{
element* temp = first;
while(temp->next)
{
temp = temp->next;
}
temp->next = nowy;
}
}
void list::show_list()
{
element* temp = first;
if(temp == 0)
{
cout << "List is empty." << endl;
cout << "No smallest element " << endl;
cout << "No largest element" << endl;
}
else
{
while(temp)
{
cout << temp->number << endl;
temp = temp->next;
}
cout << "the smallest element: : " << first->number << endl;
if(first->next == 0)
{
cout << "Largest element = Smallest element :)" << endl;
}
}
}
void list::segregate()
{
element* new_first = NULL;
element* prv;
element* temp;
element* maks;
while(first)
{
maks = first;
prv = NULL;
temp = first;
while(temp->next)
{
if(temp->next->number > maks->number)
{
prv = temp;
maks = temp->next;
}
temp=temp->next;
}
if (prv)
{
prv->next = maks->next;
}
else
{
first = maks->next;
}
maks->next = new_first;
new_first = maks;
}
first = new_first;
}
int main()
{
int n=0;
int number=0;
list* base = new list;
cout << "Size of list: " << endl;
cin >> n;
for(int i = 0; i < n; i++)
{
cout << "No " << i+1 << ": ";
cin >> number;
base->fill_list(number);
}
base->segregate();
base->show_list();
//base->maksimum();
delete(base);
return 0;
}
How can I do that?
ok. you're right, but I thought that my code shows my work. not matter :)
i solved my problem. My function: ^^
void list::show_list()
{
element * temp = first;
if( temp == 0 )
{
cout << "List is empty." << endl;
cout << "No smallest element " << endl;
cout << "No largest element" << endl;
}
else
{
while( temp->next != 0 )
{
temp = temp->next;
}
cout << "The largest element: " << temp->number << endl;
cout << "The smallest element: " << first->number << endl;
}
}
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;
}