c++ templates implementing on structures - c++

There is something wrong with this C++ code. I've compiled it in VC ++ 6.0. It's giving the error "cannot deduce template argument for type"... The problem is in the display function.
Here's the code:
#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
template <class type>
struct one
{
type data;
one *next;
};
one<int> *head, *temp, *mid, *del = NULL;
template <class type>
void athead(type value)
{
one *node = new one;
node->data = value;
node->next = head;
head = node;
}
template <class type>
void add_at_tail(type value)
{
one *node = new one;
node->data = value;
node->next = NULL;
if(head == NULL)
{
head = node;
temp = head;
}
while(temp->next != NULL)
{
temp = temp->next;
}
if(temp != node)
{
temp->next = node;
}
}
template <class type>
void display()
{
one<type> *temp = new one;
temp = head;
cout << "\n\n" << endl;
while(temp != NULL)
{
cout << " " << temp->data << " " << "->";
temp = temp->next;
}
cout << "\n\n\n";
}
int main()
{
int a, b, c;
cout << "Enter the data: " << endl;
cin >> a;
add_at_tail(a);
cout << "Enter the data: " << endl;
cin >> b;
add_at_tail(b);
cout << "Enter the data: " << endl;
cin >> c;
add_at_tail(c);
display();
return 0;
}

Couple problems here, at least:
First, you have defined the template function:
template<class type>
void display()
{
one<type> *temp=new one;
temp=head;
cout<<"\n\n"<<endl;
while(temp!=NULL)
{
cout<<" "<<temp->data<<" "<<"->";
temp=temp->next;
}
cout<<"\n\n\n";
}
This line is malformed, because one is not a complete type (one is a class template)
one<type> *temp=new one;
You need to do this:
one<type> *temp=new one<type>;
Then down in the client code, you attempt to call the function template like this:
display();
But display is a function template with no arguments, so there's no way the compiler can deduce the type of it's template parameter type. You must specify the type of type at the call point.
display<int>();
There are also logic errors with the implementation of display(). You instantiate a single copy of one and don't initialize it. You then try to iterate over it like it's a linked list, but it's not -- its just some uninitialized node you just created. You probably want to pass in the linked list you're trying to iterate over. Something along these lines:
template<class type>
void display(const one<type>& head)
{
one<type> const * temp = &head;
cout<<"\n\n"<<endl;
while(temp!=NULL)
{
cout<<" "<<temp->data<<" "<<"->";
temp=temp->next;
}
cout<<"\n\n\n";
}
Now that display takes parameters mentioned in the template, the compiler is able to deduce its type. You probably want to call it like this:
display(head);

You've got a call to display(), but that's a template function and you've given the compiler no way to deduce the template argument. You can specify it explicitly as display<int>(); (but the code has other problems besides that - you're writing one in a few places, when you should probably be writing one<type>).

Well, since display() takes no arguments, how do you think the compiler can figure out what type you expect type to be reified to? You could give display() a dummy type argument, or, better, move all these methods into a class so the type parameter can be figured out just once for the whole program.

Replacing one *node = new one; with one<type>* node = new one<type>; and altering display(); in main() to display<int>(); fixed all the compiler errors.

Related

I made my own custom stack and want to know how is there a way to iterate through the stack in reverse

This is the interface file
#ifndef STACK_H
#define STACH_H
#include<iostream>
using namespace std;
class Stack
{
struct StackFrame{
char data;
StackFrame* next;
};
StackFrame* head;
public:
Stack();
void push(char);
char pop();
void empty();
bool check_empty();
void print();
//Note:This code prints the data in stack format !!!
~Stack();
};
#endif // !STACK_H
This is the implementation file
#include "Stack.h"
Stack::Stack():head(nullptr){}
void Stack::push(char c)
{
StackFrame* temp = new StackFrame;
temp->data = c;
temp->next = nullptr;
if (head == nullptr)
{
head = temp;
return;
}
temp->next = head;
head = temp;
}
char Stack::pop()
{
if (head == nullptr)
{
cerr << "There is nothing in the stack to pop at the moment!!!" << endl;
return '\0';
}
StackFrame* holder = head;
char temp_chr = holder->data;
head = head->next;
free(holder);
holder = nullptr;
return temp_chr;
}
void Stack::empty()
{
StackFrame* holder;
while(head!=nullptr)
{
holder = head;
head = head->next;
free(holder);
}
holder = nullptr;
head = nullptr;
}
bool Stack::check_empty()
{
return head==nullptr;
}
void Stack::print() {
if (head == nullptr)
{
cerr << "Nothing in stack at the moment :( " << endl;
return;
}
StackFrame* holder = head;
while (holder != nullptr)
{
cout << holder->data;
holder = holder->next;
}
cout << endl;
}
Stack::~Stack()
{
empty();
}
This is the application file
#include"Stack.h"
#include<string>
int main()
{
int num;
string push;
Stack st;
cout << "Enter your name = ";
getline(cin, push);
for (int i = 0; i < push.length(); i++)
{
st.push(push[i]);
}
st.print();
cout << "How many times do you want to pop? = ";
cin >> num;
for (int i = 0; i < num; i++)
{
st.pop();
}
st.print();
return EXIT_SUCCESS;
}
Can someone help me out on how to reverse iterate in this stack class which i made myself using the concept of linked list, i googled a bit and got the gist of things to use tail , Can someone elaborate another way if possible please or share a link to a site. It will help me out later a lot when i start working on binary trees and if i ever need to reverse iterate in the binary tree nodes.
First of all as mentioned above, stack is LIFO data structure and thus should use another data structure for that purpose.
Second, you can use second stack and copy data over to new stack, which is expensive.
Third option would be to go from the top and kip a track and store pointer to the previous node and to the pointer that point to the previous of previous node. Something like this:
struct reverseStack {
StackFrame* node;
reverseStack* previousPointer;
reverseStack (StackFrame* n, ReverseStack* p) :
node (n), previousPointer(p) { }
}
than using simple for loop you create pointer to the top, and go to the next and store that info into this structure. In your code you have something like this:
reverseStack top (nullptr, topFrame);
StackFrame currentFrame = top->next();
ReverseStack current; = top;
while (currentFrame != nullptr) {
// alghoritm for linking previous nodes.
}
I think you should add a second Stack object rather than a second list.
Recursive algorithm would have worked fine (use the recursive call stack as your "reverse" stack).
void Stack::print(StackFrame *pCurr) {
if (pCurr != nullptr)
{
print(pCurr->Next);
cout << pCurr->ch;
}
}
void Stack::print() {
if (head == nullptr)
{
cerr << "Nothing in stack at the moment :( " << endl;
return;
}
print(head);
cout << endl;
}

How do i solve overloaded function with no contextual type information error?

I'm doing a program about doubly linked list. I have function find that helps locate, if per se, no. 7 is anywhere within that list. This function works fine and returns pointer to that node.
Then I have function afterElement that inserts for example no. 3 after no. 7, So it uses pointer to find function as parameter. I think this is where the problem stems from, but I might be wrong, you be the judge.
I wanna know, how can I correctly use this function? Is there something wrong with how I pass parameters or else?
The error I get is "overloaded function with no contextual type information".
Here is the relevant code:
#include <iostream>
using namespace std;
struct node {
int data;
node* prev;
node* next;
};
node* find(int,node*&);
void afterElement(int,int,node*&,node*&,node* (*find)(int, node*&));
int main() {
node* head = NULL;
node* tail = NULL;
// The program itself has a menu that allows for input of value in list but
// for the sake of relevancy and shortness of code I dropped it out from here
int x, y;
cout << "Insert 2 values: value you wish to insert, and value you wish to insert it after. ";
cin >> x;
cin >> y;
afterElement(x,y,head,tail,(*find)(y,head)); // here is the error "overloaded function..."
return 0;
}
node* find(int x,node*& head) {
node* curr = head;
while ((curr != NULL) && (curr->data != x))
curr = curr->next;
return curr;
}
void afterElement(int x,int after,node*& head,node*& tail,node* (*find)(int x, node*& head)) {
node* N;
node* compared = (*find)(after,head);
N->data = x;
if (compared == NULL)
cout << "There is no element " << after << " in the list!\n";
else {
if (compared->next == NULL) {
compared->next = N;
N->prev = compared;
N->next = NULL;
tail = N;
} else {
compared->next->prev = N;
N->next = compared->next;
compared->next = N;
N->prev = compared;
}
}
}
If you want to pass a function as an argument to another function, you just need to use the function name, not the entire call expression.
afterElement(x,y,head,tail,find);
This is the minimal fix that causes your program to compile. Live demo. Note this only demonstrates that the compilation errors are fixed, not that the program works!
In addition, because you are using namespace std, you are getting incomprehensible error messages, since the compiler cannot figure out what find you have in mind, your own or std::find. If you get rid of using namespace std, your error message becomes much clearer:
error: cannot convert ‘node*’ to ‘node* (*)(int, node*&)’
Live demo. Never use using namespace std.
However you may want to consider removing find from the parameter list of afterElement. afterElement doesn't need to be told which function to call in order to find an element.
void afterElement(int x,int after,node*& head,node*& tail)
would work just fine.
Passing a pointer to a node instead of int after will also work:
void afterElement(int x, node* after, node*& head, node*& tail)
Call afterElement(x, y, find(x, head), head, tail) to use this variant. Note you don't need to say (*find)(x, head).
There are more problems with your code than this compilation error. For example
node* N;
...
N->data = x;
is incorrect. You have not initialised N, it doesn't point anywhere, so you cannot use -> on it.
Another problem is that your program never modifies head, so the list doesn't have a chance to contain anything. This perhaps should be fixed by adding more functions (maybe something like beforeElement).
I observe that you want to pass the "find" function as an argument to afterElement function.
Sure you can pass a function as an argument to other function. A function also gets stored in a memory location. This memory location is stored in the variable named same as the function name (in this case "find").
Now you are receiving the find function argument as a pointer in the afterElement function, so it is expecting an address, but you are passing the whole function. That's the reason why it is giving a compilation error.
The correct code looks like :
#include <iostream>using namespace std;
struct node {
int data;
node* prev;
node* next;
};
node* find(int,node*&);
void afterElement(int,int,node*&,node*&,node* (*find)(int, node*&));
int main() {
node* head = NULL;
node* tail = NULL;
// The program itself has a menu that allows for input of value in list but
// for the sake of relevancy and shortness of code I dropped it out from here
int x, y;
cout << "Insert 2 values: value you wish to insert, and value you wish to insert it after. ";
cin >> x;
cin >> y;
afterElement(x,y,head,tail,find); // modified the passing argument
return 0;
}
node* find(int x,node*& head) {
node* curr = head;
while ((curr != NULL) && (curr->data != x))
curr = curr->next;
return curr;
}
void afterElement(int x,int after,node*& head,node*& tail,node* (*find)(int x, node*& head)) {
node* N;
node* compared = (*find)(after,head);
N->data = x;
if (compared == NULL)
cout << "There is no element " << after << " in the list!\n";
else {
if (compared->next == NULL) {
compared->next = N;
N->prev = compared;
N->next = NULL;
tail = N;
} else {
compared->next->prev = N;
N->next = compared->next;
compared->next = N;
N->prev = compared;
}
}
}
I have checked with compilation, but check once for the results you are expecting.
Thanks.

How to Reverse a linked list using recursion in object oriented programming with c++?

I'm writing a program in c++ that reverse a linked list in c++.
And I have seen a lot of questions about it but my answer is not on them so please don't mark this as a duplicate!
I want to reverse a linked list using recursion and this is my full program and on Function reverse recursion() there is something wrong with it those programs ends and don't print.
I have tried to Get this function out of my class but it doesn't work and I have tried to make the head global too.
class LinkedList{
public:
Node* Head;
int Length;
LinkedList(Node* head,int c){
Head=head;
Length=c;
}
void ReverseRecursion(Node* temp,Node** Heading){
if(temp->next==0){
*Heading = temp;
cout << "This is the head item==>" << temp->value << " And this
is the Heading now " << *Heading << endl;
return;
}
ReverseRecursion(temp,Heading);
temp->next->next = temp;
temp->next = 0;
}
}
I have insert and delete and print functions in this class But i have test them and they are correct.
And on my main, I save the head element in a local variable on main and every time I pass it to the LinkedList.
And I call this function like this on main :
MyLinked.ReverseRecursion(head,&head);
When calling the recursion function you must pass a different parameter, otherwise you will have an infinite recursion until you get out of memory.
Try this version, where each time you call the function with the next element in the list, until you find the end of the list:
class LinkedList{
public:
Node* Head;
int Length;
LinkedList(Node* head,int c){
Head=head;
Length=c;
}
void ReverseRecursion(Node* temp,Node** Heading){
if(temp->next==0){
*Heading = temp;
cout << "This is the head item==>" << temp->value << " And this
is the Heading now " << *Heading << endl;
return;
}
ReverseRecursion(temp->next,Heading);
temp->next->next = temp;
temp->next = 0;
}
}
EDIT:
I show a complete testing of how my solution works. I intended to do the minimum change necessary to the original code to make it work, and the minimum is changing only one word:
#include <iostream>
using namespace std;
class Node {
public:
int value;
Node * next;
Node(int v, Node * n) : value(v), next(n) {}
};
class LinkedList{
public:
Node* Head;
int Length;
LinkedList(Node* head,int c){
Head=head;
Length=c;
}
void ReverseRecursion(Node* temp,Node** Heading){
if(temp->next==0){
*Heading = temp;
//cout << "This is the head item==>" << temp->value << " And this
//is the Heading now " << *Heading << endl;
return;
}
ReverseRecursion(temp->next,Heading);
temp->next->next = temp;
temp->next = 0;
}
void print() const;
};
void LinkedList::print() const {
cout << '{';
for (Node* node = Head; node != 0; node = node->next)
cout << ' ' << node->value; // value is public ?
cout << " }" << endl;
}
int main()
{
Node n3(3, 0);
Node n2(2, &n3);
Node n1(1, &n2);
LinkedList ll(&n1, 3);
Node *heading;
ll.print();
ll.ReverseRecursion(&n1, &heading);
ll.Head = heading;
ll.print();
return 0;
}
Output:
{ 1 2 3 }
{ 3 2 1 }

Making template type LinkedList

i have recently started studying linkedlist in c++. Although i am finding it pretty confusing but i made some functions to insert and delete and element from the linkedlist.
The program worked fine with int data type. But i want to create a linkedlist of template type and i cannot understand how to do it.
I have tried to create a function to insert the node at the first position of link list but it gives me errors like access specifier needed before node etc ...
#include <iostream>
#include<conio.h>
using namespace std;
template<class T>
class node
{
public:
T data;
node *next;
};
template<class T>
class linklist
{
public:
node <int>*head;
linklist()
{
head = NULL;
}
bool Is_Empty(node <T>*ptr)
{
if(ptr==NULL)
{
return true;
}
return false;
}
void insert_at_head(T num)
{
if(Is_Empty(head))
{
node <T>*temp = new node; // error is on this line. it says access specifier needed before node.
temp->data = num;
head = temp;
temp->next = NULL;
}
else
{
node *temp = new node;
temp->data = num;
head = temp;
temp->next = head->next;
}
}
void show_list(node <T>*ptr)
{
cout<<"\nElements in the List are : ";
while(ptr!=NULL)
{
cout<<ptr->data<<" ";
ptr = ptr->next;
}
}
};
int main()
{
cout << "Hello world!" << endl;
getch()
}

C++ Binary Search Tree Insert via Recursion

So my code is below. I'm not getting any errors and it places everything in the node just fine. But based on my debug statements Everytime anything is inserted it's finding the root. I'm not sure if that is right. But according to output file for the assignment, my answers are different when it comes to the height of the tree, the traversals, and I just flat am still having troubles with my leaf count function. Another story though.
Based on the debug statements it looks like everything is going right where they should. But I figure I might need fresh eyes. I don't see how my traversals could change at all since it is really only a matter of where I'm proccessing the node that should effect the Inorder, preorder, and postorder.
template <class T>
void BT<T>::insert(const T& item)
{
Node<T>* newNode;
newNode = new Node<T>(item);
insert(root, newNode);
}
template <class T>
void BT<T>::insert(struct Node<T> *&root, struct Node<T> *newNode)
{
if (root == NULL)
{
cout << "Root Found" << newNode->data << endl;
root = newNode;
}
else
{
if (newNode->data < root->data)
{
insert(root->left, newNode);
cout << "Inserting Left" << newNode-> data << endl;
}
else
{
insert(root->right, newNode);
cout << "Inserting Right" << newNode->data << endl;
}
}
}
My height function is as follows just in case my insert is actually fine.
template <class T>
int BT<T>::height() const
{
return height(root);
}
template <class T>
int BT<T>::height(Node<T>* root) const
{
if (root == NULL)
return 0;
else
{
if (height(root->right) > height(root->left))
return 1 + height(root-> right);
return 1 + height(root->left);
}
}
You need to change the wording of your debug statements
Really it should read (not Root node)
cout << "Leaf Node Found" << newNode->data << endl;
It is only the root when it is first called after that any call with node->left or node->right makes it an intermediate node.
To write height() I would do this:
template <class T>
int BT<T>::height(Node<T>* root) const
{
if (root == NULL) {return 0;}
return 1 + max(height(root->left),height(root->right));
}
You need to start off with your root init'd to null. Also, you are passing *&node in; it should be *node. Else you're passing a pointer to the address(or reference, I'm not sure which in this context, but both aren't going to be right). You should be passing a pointer to Node in, not a reference.
template <class T>
void BT<T>::BT()
{ root = 0;}
template <class T>
void BT<T>::insert(const T& item)
{
Node<T>* newNode;
newNode = new Node<T>(item);
insert(root, newNode);
}
template <class T>
void BT<T>::insert(struct Node<T> *root, struct Node<T> *newNode)
{
/*stuff*/
}
#Vlion:
It should be a pointer to the left/right/root pointers (i.e. a double pointer), so the posted code is correct, although somewhat unclear.
#Doug:
Consider changing your insert function thus:
template <class T>
void BT<T>::insert(struct Node<T>** root, struct Node<T>* newNode)
{
if (*root == NULL)
{
cout << "Root Found" << newNode->data << endl;
*root = newNode;
}
It makes clear your intention that you'll be changing the pointer passed as the first parameter (or rather, the pointer whose address will be passed as the first parameter.) It will help avoid confusion such as the one that just happened.
The calls to this insert(), such as:
insert(&root, newNode);
will also reflect your intention of changing the pointer's value. This is a matter of style, though, so I can't argue if you don't want to change.
As for checking whether the tree is "correct," why not draw it out and see for yourself? Something along the lines of:
template class<T>
void printTree(struct Node<T>* node, int level=0)
{
if (!node) {
for (int i=0; i<level; ++i)
cout << " ";
cout << "NULL" << endl;
return;
}
printTree(node->left, level+1);
for (int i=0; i<level; ++i)
cout << " ";
cout << node->data << endl;
printTree(node->right, level+1);
}
(Untested code)