This my C++ code:
#include <iostream>
class Node
{
public:
int data;
Node* prev;
Node* next;
};
class Doublyll
{
private:
Node* head;
Node* tail;
public:
Doublyll();
Doublyll(int A[], int num);
~Doublyll();
friend std::ostream& operator<<(std::ostream& os, const Doublyll& src);
int Length(Node* p);
};
// Default Constructor will SET head and tail to NULL
Doublyll::Doublyll()
: head(NULL), tail(NULL)
{
}
// Explicit Construcor
Doublyll::Doublyll(int A[], int num)
: head(NULL), tail(NULL)
{
// std::cout << "Explicit Constructor called!\n";
Node** p = &head;
for (int i = 0; i < num; i++)
{
Node* t = new Node;
t->data = A[i];
if (head == NULL)
t->prev = NULL;
else
t->prev = tail;
t->next = NULL;
*p = t;
p = &(t->next);
tail = t;
}
}
// Destructor
Doublyll::~Doublyll()
{
// std::cout << "Desctructor called!\n";
Node* p = head;
Node* tmp;
while (p != NULL)
{
tmp = p;
p = p->next;
delete tmp;
}
}
// Display using Overloading << Operator
std::ostream& operator<<(std::ostream& os, const Doublyll& src)
{
Node* tmp;
for (tmp = src.head; tmp != NULL; tmp = tmp->next)
std::cout << tmp->data << " ";
std::cout << std::endl;
return os;
}
// Find Length how much Node in linked list
int Doublyll::Length(Node* p)
{
static int count = 0;
if (p != NULL)
{
count++;
Length(p = p->next);
}
return count;
}
int main()
{
int A[] = {2, 4, 6, 8, 10, 12, 14};
int size = sizeof(A) / sizeof(A[0]);
// Create object and linked list
Doublyll l1(A, size);
// Display linked list
std::cout << l1;
// Get length of linked list
int c = l1.Length(l1.head);
std::cout << c << std::endl;
return 0;
}
As you can see, I try to practice Doubly Linked List. Then, I want to count total Node in my linked list.
You can see in int Doublyll::Length(Node* p) I try to Count it using Recursion. Just because I want to practice it with Recursion. But, in my main() somewhow this code: int c = l1.Length(l1.head); said "Head is inaccessible"
I know that is because Head is Private in my Doublyll class. And I can simply change it to Public. OR I can write a function getHead() which will return Head pointer and then pass it as arguments.
So, Is there a way to dircetly pass it from my main() without change the member to public or write a getHead() function? or maybe there's another way to write a Recursion based on my problem, which in the future can also implement it to another recursion like display()? Because it seems like difficult to access if everything is inside class.
Maybe you can also review how I create a Doubly Linked List. Thank you!
Make int Doublyll::Length(Node *p) a private member function and add a public int Doublyll::Length() that takes no arguments and does:
int Doublyll::Length()
{
return Length(head);
}
(also you should probably make both of them const - int Doublyll::Length() const since they shouldn't modify anything)
Then just call l1.Length() in main.
Users of Doublyll shouldn't know about the internals of the class, and it doesn't make sense to ask a Doublyll object for the length from some node that it might not even own. Making Length(Node *p) private prevents nonsense things like l1.Length(l2.head).
As for your implementation of int Doublyll::Length(node *p) it's just wrong. As a comment mentions, you're using a static int count to track the length which will give you the wrong answer if you call the function multiple times. Plus your recursion is wrong since you aren't using the result of the recursive call. Do something like this instead:
int Doublyll::Length(Node *p) const
{
// Base case - no nodes
if (p == nullptr)
return 0;
// Recursive case
return 1 + Length(p->next);
}
Or a solution that allows for tail call optimization:
int Doublyll::Length(Node *p, int count) const
{
// Base case - no more nodes - return count
if (p == nullptr)
return count;
// Recursive case - increment count and go to the next node
return Length(p->next, count+1);
}
int Doublyll::Length() const
{
return Length(head, 0);
}
A common technique when implementing recursive functions is to have one public non-recursive function to start things off (say, Doublyll::Length()), and a second private helper function that actually performs the recursion (something like Doublyll::LengthRecursive()).
This could look something like:
int Doublyll::LengthRecursive(Node* p)
{
static int count = 0;
if (p != NULL)
{
count++;
Length(p = p->next);
}
return count;
}
int Doublyll::Length()
{
return LengthRecursive(head);
}
One way of handling a situation like this is to use two member functions: one that is the public interface and one that is private but has the signature you want for the recursive call.
For example:
class Doublyll
{
private:
Node* head;
Node* tail;
int LengthAux(Node* p); //private recursive implementation
public:
Doublyll();
Doublyll(int A[], int num);
~Doublyll();
friend std::ostream& operator<<(std::ostream& os, const Doublyll& src);
int Length(); // public interface
};
int Doublyll::Length() {
return LengthAux(head);
}
// Find Length how much Node in linked list
int Doublyll::LengthAux(Node* p)
{
static int count = 0;
if (p != NULL)
{
count++;
LengthAux(p->next);
}
return count;
}
...
This is a pretty common pattern used by implementations involving recursion. It is the nature of recursive calls that the signature of the recursive guts of the function is often different than the natural signature of calling the function externally.
Related
I am learning how to program in C++, and have looked at linked lists. I have found many code snippets to get me started.
The code I am playing with is from studytonight. I understand how to insert nodes into a list. But what if I want to create a linked list and fill x-many nodes at once in a loop? The for loop in my main() works fine, but when I try turning it into a function, such as arrayToList(), I am running into problems.
The function would simply use the entries of an array and turn them into the data (like an index) and a second value stored in the node. Obviously, the function needs to return a list to continue any manipulation, like deleting or replacing, etc, but also needs to receive a list as a parameter as the created list inside won't exist outside this function. The call to traverse the list inside the for loop is just to highlight that inside the function that list isn't empty.
I am a little lost as to make the function work, and would appreciate any help regarding a method to iteratively add x-many at once nodes to a linked list. I hope I have explained my problem well enough.
#include <iostream>
#include <stdlib.h>
using namespace std;
struct node
{
int data; // Data
node *prev; // A reference to the previous node
node *next; // A reference to the next node
double x;
};
class Doubly_Linked_List
{
node *front; // points to first node of list
node *end; // points to first las of list
public:
Doubly_Linked_List()
{
front = NULL;
end = NULL;
}
void add_front(int, double );
void forward_traverse();
void arrayToList(int[], int);
};
void Doubly_Linked_List :: add_front(int d, double x)
{
// Creating new node
node *temp;
temp = new node();
temp->data = d;
temp->x = x;
temp->prev = NULL;
temp->next = front;
// List is empty
if(front == NULL)
end = temp;
else
front->prev = temp;
front = temp;
}
void Doubly_Linked_List :: forward_traverse()
{
node *trav;
trav = front;
while(trav != NULL)
{
cout<<trav->data<<" (" << trav->x << " )" << endl;
trav = trav->next;
}
}
void Doubly_Linked_List :: arrayToList(int arr[], int n)
{
Doubly_Linked_List list;
for(int i=n-1; i>=0;i--)
{
cout << i << endl;
list.add_front(arr[i], arr[i]);
list.forward_traverse();
}
}
int main()
{
Doubly_Linked_List list;
int arr[] = { 1, 2, 3, 4, 5 };
int n = sizeof(arr) / sizeof(arr[0]);
// for (int i= 1; i< 10; i++)
// {
// list.add_front(i, i*2);
// }
list.arrayToList(arr, n);
cout << "after filling arrayList " << endl;
list.forward_traverse();
}
For starters the function should be declared like
void arrayToList( const int[], size_t );
and the function can be defined the following way if to take into account this commented statement in main
// list.add_front(i, i*2);
void Doubly_Linked_List :: arrayToList( const int arr[], size_t n )
{
while ( front )
{
node *current = front;
front = front->next;
delete current;
}
end = nullptr;
for ( size_t i = n; i != 0; i-- )
{
add_front( arr[i-1], 2 * arr[i-1] );
}
}
Though it would be better to declare the function at least like
void arrayToList( const std::pair<int, double>[], size_t );
Your arrayToList() is creating and filling a local Doubly_Linked_List object named list, which is a separate object from the list in main(). Creating a local object is fine (it is good for exception safety), but arrayToList() is then discarding that local object and not assigning its data to the object that arrayToList() was actually called on. That is why your call to forward_traverse() in main() does not see anything changed.
Try this instead:
#include <utility>
void Doubly_Linked_List :: arrayToList(int arr[], int n)
{
Doubly_Linked_List list;
for(int i=n-1; i>=0;i--) {
list.add_front(i, arr[i]);
}
// add this
std::swap(front, list.front);
std::swap(end, list.end);
}
Otherwise, get rid of the local list and modify the data in this instead:
void Doubly_Linked_List :: arrayToList(int arr[], int n)
{
// optional: clear the called-on object first, if needed...
// clear(); // <-- add this method to Doubly_Linked_List...
for(int i=n-1; i>=0;i--) {
add_front(i, arr[i]);
}
}
Otherwise, change arrayToList() to be static, and then have it return a new Doubly_Linked_List object (just make sure you also implement a copy constructor, copy assignment operator, and destructor, per the Rule of 3/5/0):
class Doubly_Linked_List
{
...
// implement these!
~Doubly_Linked_List();
Doubly_Linked_List(const Doubly_Linked_List &);
Doubly_Linked_List& operator=(const Doubly_Linked_List &);
// and change this
static Doubly_Linked_List arrayToList(int[], int);
...
};
Doubly_Linked_List Doubly_Linked_List :: arrayToList(int arr[], int n)
{
Doubly_Linked_List list;
for(int i=n-1; i>=0;i--) {
list.add_front(i, arr[i]);
}
return list;
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5 };
int n = sizeof(arr) / sizeof(arr[0]);
Doubly_Linked_List list = Doubly_Linked_List::arrayToList(arr, n);
cout << "after filling arrayList " << endl;
list.forward_traverse();
}
Today, I have learned about the Binary Search Tree, and I am trying to implement it, but I got a problem.
Assume that I have a Struct like this:
struct Node {
int v;
Node* left = NULL;
Node* right = NULL;
}
Below it, I have:
// At the beginning, root is NULL
Node* root = NULL;
Node* new_node(int v) {
Node* n = new Node;
n->v = v;
return n;
}
void insert(int v) {
// At the beginning, root is NULL
Node* c = root;
while (c != NULL) {
if (v < c->v) {
c = c->left;
} else {
c = c->right;
}
}
c = new_node(v);
}
And in the main code, I tested my implementation by using this code:
int main() {
insert(5);
}
When I use insert(5), in insert function, the variable c will be root, and because root at that time is NULL, so c will equal to new_node(v). But when I print root->v it returns nothing.
Did I make something wrong??
In your code you do not modify root after initialization. root is always NULL. This
Node* c = root;
// ...
c = new_node(v);
will not change root. It merely declares a local variable c, initializes it with the value of root and assigns a new value to it.
If you want to change the value of something inside a function you can pass it by reference, pointers are no different with respect to that. For example:
#include <iostream>
struct Node {
int v;
Node* left = NULL;
Node* right = NULL;
};
Node* root = NULL;
Node*& find_insertion(Node*& ptr, int v){
if (ptr == NULL) return ptr;
if (v < ptr->v) {
return find_insertion(ptr->left,v);
} else {
return find_insertion(ptr->right,v);
}
}
void insert_at(Node*& ptr,int v){
Node*& insertion = find_insertion(root,v);
insertion = new Node;
insertion->v = v;
}
void insert(int v){
insert_at(root,v);
}
int main() {
insert(5);
std::cout << root->v;
}
Next you should take a look at smart pointers (std::unique_ptr) to avoid leaks or compilcated manual memory managment.
I've been given a class declaration (create a list with nodes) in C++ that I need to define and I'm having trouble with one of the member functions: void print() const;
Question: How can I go about traversing and printing out the first->value's without removing const in the function declaration i.e. altering first? The function below yields an error: expression must be a modifiable lvalue.
Class declaration (only details of relevance)
class List {
public:
.
.
.
void print() const;
int size();
void add(int d);
private:
int sz = 0;
struct Node {
int value;
Node* next;
Node(int v, Node* n) : value(v), next(n) {}
};
Node* first; // pointer to the first node
};
Class definition (only details of relevance)
void List::print() const {
while (first != NULL) {
cout << first->value << endl;
first = first->next;
}
}
int List::size() const {
return sz;
}
void List::add(int d) {
if (size == 0)
first = new Node(d, NULL), sz++;
else {
Node* newnode = new Node(first->value, first->next);
first = new Node(d, newnode);
sz++;
}
}
Thanks for your time
The trick is to make a copy of first and only modify the copy: (not tested)
Node* firstCopy = first;
while (firstCopy != NULL) {
cout << firstCopy->value << endl;
firstCopy = firstCopy->next;
}
I'm trying to implement a templated singly linked list and I'm fairly new to C++
#include <iostream>
#include <string>
#define NEWL "\n"
#define PRINT(s) std::cout << s
#define PRINTL(s) std::cout << s << NEWL
#define PRINTERR(e) std::cerr << e << NEWL
////// Class for a Node
template<class Data> class Node {
Node<Data>* next_ptr;
Data data;
public:
Node(Node<Data>* nxt_ptr) :next_ptr(nxt_ptr) {};
Node(Data d, Node<Data>* nxt_ptr) :data(d), next_ptr(nxt_ptr) {};
Node<Data>* get_next() { return next_ptr; }
Data& get_data() { return data; }
friend std::ostream& operator<<(std::ostream& out, const Node<Data>& node) {
out << node.data;
return out;
};
};
////// Class for a SinglyLinkedList
template<class Data> class SLinkedList {
Node<Data>* head_ptr;
int max_size;
public:
SLinkedList() : head_ptr(nullptr) {};
bool is_empty() {
return head_ptr == nullptr;
};
bool is_full() {
return get_size() == max_size;
};
int get_size() {
if (is_empty()) {
return 0;
}
int count = 0;
for (Node<Data>* it_ptr = head_ptr; it_ptr != nullptr; it_ptr = it_ptr->get_next()) {
count++;
}
return count;
};
void add(Data d) {
if (is_full()) {
throw std::exception("List is full!");
}
Node<Data> new_node(d, head_ptr);
head_ptr = &new_node;
};
void print_content() {
int count = 1;
PRINTL("This list contains:");
for (Node<Data>* it_ptr = head_ptr; it_ptr != nullptr; it_ptr = it_ptr->get_next()) {
PRINTL("\t["<< count << "]" << " at " << it_ptr << " : " << *it_ptr);
count++;
}
}
};
////// Main function
int main()
{
SLinkedList<int> sll;
sll.add(42);
sll.print_content();
}
I can't get this to work. Somehow iterating the list with for-loops does not work. It always results in an Reading Access Violation Exception about a pointer to 0xCCCCCCD0 and I have no idea how to fix this.
Your add function is incorrect
Node<Data> new_node(d, head_ptr);
creates a new function local Node in add. You then set head to the address of that local variable. When the function ends all local variables are destroyed so now head points to an object that no longer exists.
To fix that you need to use the new keyword to create a dynamic object that will live on after the function ends.
Node<Data>* new_node = new Node(d, head_ptr);
head_ptr = new_node;
The down side with this is you need to remember to call delete on all of the nodes you created in the list destructor.
You also have some other bugs in your code. You never set max_size in your constructor so using it at all except to give it a value is undefined behavior as we have no idea what the value of it is going to be. You also never increase the size of the list when you add nodes into the list.
How to implement push_front() method for a singly linked list as its member function? The code below does not compile (error: lvalue required as left operand of assignment), because you cannot assign to this pointer. What is a way round this?
#include<algorithm>
using namespace std;
class ListElem{
public:
ListElem(int val): _val(val){}
ListElem *next() const { return _next; }
void next(ListElem *elem) { _next = elem; }
void val(int val){ _val = val; }
int val() const { return _val;}
void print();
void push_front(int);
private:
ListElem *_next;
int _val;
};
void ListElem::push_front(int val)
{
ListElem *new_elem = new ListElem(val); //new node
new_elem->next( this ); // new node points to old head
this = new_elem; // make new node the new head, error!
return;
}
void ListElem::print()
{
ListElem *pelem = this;
while(ListElem *pnext_elem = pelem->next())
{
cout << pelem->val() << ' ';
pelem = pnext_elem;
}
cout << pelem->val() << endl;
}
int main()
{
//initialization
ListElem *head = new ListElem(1);
ListElem *elem = head;
for (int ix = 2; ix < 10; ++ix)
{
ListElem *elem_new = new ListElem(ix);
elem -> next(elem_new);
elem = elem_new;
}
head->print();
//insert at the beginning
head->push_front(7);
head->print();
}
Logically, push_front() must be a method of List class and not of a ListElement class
You're using this incorrectly. You want to have a static member called, say, ListElem *head and use that where you were using this. You'll also have to initialise it.
If you really want to do it that way, you can do it like this:
void ListElem::push_front(int val)
{
ListElem *new_elem = new ListElem(_val);
_val = val;
new_elem->next(_next);
_next = new_elem;
}
This will replace the data in the "current" node with the new data, and move the "current" data to the new node, which will yield the same list content.
But it's not really correct to conflate a list with its nodes.
The book you linked takes a very non-OO approach to the whole thing (both the Java and the C++ examples look like transliterated C), and conflating the type of a list with the type of its nodes is pretty certain to lead to bugs later.
For instance, if you do this
ListElem* x = head;
head->push_front(99);
then the contents of *x will have changed, which isn't really what you would expect.