0

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!

Kevinkun
  • 21
  • 5
  • `static int count = 0;` - `static` variables in functions are only initialized the *first* time the function is called, so this will give the incorrect result if you call `Length` a second time. – 0x5453 Jul 21 '21 at 17:54

3 Answers3

4

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);
}
Kevin
  • 6,993
  • 1
  • 15
  • 24
2

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);
}
effect
  • 1,279
  • 6
  • 13
2

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.

jwezorek
  • 8,592
  • 1
  • 29
  • 46