recursive function that takes a pointer to the middle of an infinite doubly linked list and Search for a key - c++

Provide a recursive function that takes a pointer to the middle of an infinite
doubly linked list along with an integer key and searches the list for the given key. The
list grows infinitely in both directions. Your algorithm should be able to find the key if it is
present in the list, otherwise it should continue the search infinitely.
This is The question i'm provided with and i can't understand how To recursivly search on both sides. either i'll have to write 2 functions i.e one for searching left other for right side.
but can it e searched in one function?
this is my code:
void searchmiddle(Node<T>* middle, int key,int index) {
if (middle == NULL) {
return ;
}
if (head == NULL) {
return ;
}
/* if (middle->next == head) {
return false ;
}*/
if (middle->data == key) {
cout << "key found at index "<<index << endl;
key = 0;
return ;
}
searchmiddle(middle->prev, key, index - 1);
searchmiddle(middle->next, key, index + 1);
}
code works for key next to middle pointer..

You could relay the call to a function that instead takes two Node<T>*, left and right. You then check if either one is the correct node and return if anyone is, otherwise you call the same function again recursively while stepping both left and `right.
template<class T>
Node<T>* searchmiddle(Node<T>* left, Node<T>* right, const T& key) {
if (left->data == key) return left;
if (right->data == key) return right;
return searchmiddle(left->prev, right->next, key);
}
template<class T>
Node<T>* searchmiddle(Node<T>* middle, const T& key) {
return searchmiddle(middle, middle->next, key);
}
This is purely theoretical though since it'll most probably stop working when the stack is full. It also doesn't check for nullptr since the list is said to be infinite.
Nothing in the requirement says anything about printing an index so I made it return a pointer to the found Node<T> instead.

You should not use recursion, because the requirement is that the search should continue infinitely for as long as there is no match. The call stack is limited, and recursion consumes it, meaning the recursion cannot go on indefinitely.
By consequence, the search should happen through iteration and not recursion.
You should use two pointers, one that will move along the prev pointers to the left, and the other that will move along the next pointers to the right. As apparently it is needed to report the index where the match was found, you should accompany those two pointers with an index.
There should not be a reference to a head pointer (where is it defined?), as an infinite list has no head. The challenge description suggests that the list extends continually in both directions, so there will be no end node like a head or a tail.
The code could be something like this:
void searchmiddle(Node<T>* middle, int key, int index) {
Node<T>* left = middle;
int leftIndex = index;
Node<T>* right = middle->next;
int rightIndex = index + 1;
while (1) { // Search continues as long there is no match
if (left->data == key) {
cout << "key found at index " << leftIndex << endl;
return;
}
left = left->prev;
leftIndex--;
if (right->data == key) {
cout << "key found at index " << rightIndex << endl;
return;
}
right = right->prev;
rightIndex++;
}
}
This is quite a theoretical challenge, as the only way to have a really infinite linked list, is to make it circular. It also means that there is a possibility that the key will never be found giving you a function that never finishes.

Related

Binary Search Tree using the most frequent node to print out certain statements

I have a binary search tree that I want to use to be able to give a certain output for the most common node but i'm having a hard time doing that. I already have code that prints out how many times the node is entered into the tree and which one is the most frequent but I don't know how to write the if statement that would compare the values and be able to output certain things if one was greater than the other. I have been working on this for hours and just can't get the right output please help.
So if i have more a's i want that to have a certain output or if i have more b's that should have a different output etc.
For starters, change the node definition to look more like the one below. This definition initializes all the struct's fields to their zero values. For me, this change prevented an access violation at the line if (p->data == q->data), probably because the next pointer was not initialized to nullptr.
struct node {
char data{};
int count{};
node *left{};
node *right{};
int height{};
node *next{};
};
Similarly, my compiler warns about an uninitialized variable res. So that too should be initialized like char res{};.
This seems to work for the maxChar function. The second overload calls the first overload, which calls itself recursively. They don't have to have the same names.
char maxChar(node *node, int max, char res) {
if (node != nullptr) {
res = maxChar(node->left, max, res);
if (node->count > max) {
max = node->count;
res = node->data;
}
res = maxChar(node->right, max, res);
}
return res;
}
char maxChar(node *node) {
int max{};
char res{};
return maxChar(node, max, res);
}
Then if needed, you could do something like this:
char maxCh = maxChar(root);
switch (maxCh) {
case 'A': cout << "Your recommendation is A." << endl;
break;
case 'B': cout << "Your recommendation is B." << endl;
break;
}

how to return an index from a function?

I'm working on a phonebook program. I need to use a position returned by my findContact function and use it as an index in my deleteContact function.
void AddressBook::deleteContact(std::string nameMatch) //need to implement find contact && not found if there is a space at end of name
{
if (length == 0)
{
std::cout << "Phonebook is empty" << std::endl;
return;
}
findContact(nameMatch);
std::cout << phoneBook[position]->name << " deleted" << std::endl;
phoneBook[position] = phoneBook[length - 1]; //how to use position
length--;
return;
}
I use a binary search because it is instructed by my professor.
int AddressBook::findContact(std::string nameMatch)
{
int first = 0;
int last = length - 1;
int middle;
int position = -1;
bool found = false;
while (!found && first <= last)
{
middle = (first + last) / 2;
if (phoneBook[middle]->name == nameMatch)
{
found = true;
position = middle;
}
else if (phoneBook[middle]->name > nameMatch)
{
last = middle - 1;
}
else
{
first = middle + 1;
}
}
return position;
}
It's mostly incomplete but I'm trying to figure out how to use the position
returned from my findContact function and use it in my deleteContact.
Save the return value in a local variable.
auto position = findContact(nameMatch);
I'm not quite sure what you mean by how to use position. If your issue is, how you technically get position from your find method to your delete method, #DeviationN's answer is your solution.
But you're maybe asking how to do the deletion in your phonebook container (it's probably a vector?). What you've done is overwriting your entry to be deleted by the last entry in your phonebook. However, this is going to violate the sort order (in most cases). But if you use binary search, it is a necessary condition that your phonebook is sorted.
Instead, delete your entry at position via
phoneBook.erase( phonebook.cbegin() + position );
end either decrement your length as you did or reset it like
length = phoneBook.size();
(Here I have assumed that phoneBook is a std::vector or std::deque)
Edit: I just noticed that phoneBook is a container of pointers, so don't forget to do
delete phoneBook[ position ];
before erasing this element ( unless you use smart pointers ;).

search function causes program to crash

I have been going through the debugger but can't seem to pinpoint exactly what is going wrong. I have come to my own conclusion i must be missing a nullptr check somewhere or something. If anyone can provide some help it would be greatly appreciated.
error message from debugger
error msg
which looks like makes the program crash on this line:
if (node->children_[index] == nullptr) {
search function
Node* search(const string& word, Node* node, int index) const {
Node* temp;
//same as recurssive lookup just difference is returns node weather terminal or not
if (index < word.length()) {
index = node->getIndex(word[index]);
if (node->children_[index] == nullptr) {
return nullptr;
}
else {
temp = search(word, node->children_[index], index++);
}
}
return temp; // this would give you ending node of partialWord
}
Node struct for reference
struct Node {
bool isTerminal_;
char ch_;
Node* children_[26];
Node(char c = '\0') {
isTerminal_ = false;
ch_ = c;
for (int i = 0; i < 26; i++) {
children_[i] = nullptr;
}
}
//given lower case alphabetic charachters ch, returns
//the associated index 'a' --> 0, 'b' --> 1...'z' --> 25
int getIndex(char ch) {
return ch - 'a';
}
};
Node* root_;
int suggest(const string& partialWord, string suggestions[]) const {
Node* temp;
temp = search(partialWord, root_, 0);
int count = 0;
suggest(partialWord, temp, suggestions, count);
return count;
}
Might be a very simple thing. Without digging I am not sure about the rank of the -> operator versus the == operator. I would take a second and try putting parenthesis around the "node->children_[index] == nullptr" part like this:
(node->children_[index]) == nullptr
just to make sure that the logic runs like you seem to intend.
Dr t
I believe the root cause is that you're using index for two distinct purposes: as an index into the word you're looking for, and as an index into the node's children.
When you get to the recursion, index has changed meaning, and it's all downhill from there.
You're also passing index++ to the recursion, but the value of index++ is the value it had before the increment.
You should pass index + 1.
[An issue in a different program would be that the order of evaluation of function parameters is unspecified, and you should never both modify a variable and use it in the same parameter list. (I would go so far as to say that you should never modify anything in a parameter list, but many disagree.)
But you shouldn't use the same variable here at all, so...]
I would personally restructure the code a little, something like this:
Node* search(const string& word, Node* node, int index) const {
// Return immediately on failure.
if (index >= word.length())
{
return nullptr;
}
int child_index = node->getIndex(word[index]);
// The two interesting cases: we either have this child or we don't.
if (node->children_[child_index] == nullptr) {
return nullptr;
}
else {
return search(word, node->children_[child_index], index + 1);
}
}
(Side note: returning a pointer to a non-const internal Node from a const function is questionable.)

Recursive method to find value in linked list

template<class Type>
int StringList<Type>::find(Type value)
{
int count = 0;
// Start of linked list
Node<Type> *current = head;
// Traverse list until end (NULL)
while (current != NULL)
{
// Increase counter if found
if (current->data == value)
{
count++;
}
// If not, move to the next node
current = current->next;
}
cout << value << " was found " << count << " times" << endl;
return 0;
// same function but using Recursive method
// Start of linked list
Node<Type> *current = head;
int count = 0;
// Thinking this is the base case, since its similar to the while loop
if (current == NULL)
{
return 0;
}
// same as the while loop, finding the value increase the count, or in this case just prints to console
if ((current->data == value))
{
cout << "Found match" << endl;
return 0;
}
else
{ // If it didnt find a match, move the list forward and call the function again
current = current->next;
return find(value);
}
}
the function is supposed to find the value searched and return how many times that certain value was in the linked list.
how can I turn the first method, which uses a while loop, into something that does the same thing but uses recursion?
For starters instead of the return type int it is better to use an unsigned type like for example size_t
You can use the following approach. Define two methods. The first one is a public non-static method find defined like
template<class Type>
size_t StringList<Type>::find( const Type &value ) const
{
return find( head, value );
}
The second one is a private static method with two parameters defined like
template<class Type>
static size_t StringList<Type>::find( Node<Type> *current, const Type &value )
{
return current == nullptr ? 0 : ( current->data == value ) + find( current->next, value );
}
In order to use recursion, you will need to change the signature of your find function (or add a new function with the different signature) to take a node pointer as a parameter:
template<class Type>
int StringList<Type>::find(Type value, Node<Type> *where)
{
if (where != nullptr)
{
// Do things
}
}
Then, when you traverse the list, you pass where->next to the function. Once you hit the end of the list, with a nullptr value, the stack unrolls.
A key aspect of recursion as that the function or method being used only has to process a single node of your container. It then calls itself with the next node to be processed until there are no more nodes. In order to make this work, that function needs the node to process as a parameter, which is where your current code runs into problems.
Keep in mind that the elegance and simplicity of recursion is not free. Every call that a method makes to itself eats up stack, so a sufficiently large container can result in a crash if the stack for your process is depleted.
how can I turn the first method, which uses a while loop, into
something that does the same thing but uses recursion?
The following would be closer to what you want. You really should provide an [MCVE] ... the lack of which forces many guesses and assumptions about your code.
// It looks like StringList is a class (I ignored template issues),
// and it appears that your class holds 'anchors' such as head
// StringList is probably the public interface.
//
// To find and count a targetValue, the code starts
// at the head node, and recurses through the node list.
// I would make the following a public method.
//
int StringList::findAndCountTargetValue(int targetValue)
{
int retVal = 0;
if (nullptr != head) // exists elements to search?
retVal = head->countTV(targetValue); // recurse the nodes
// else no match is possible
return(retVal);
}
// visit each node in the list
int Node::countTV(const int targetValue)
{
int retVal = 0; // init the count
if (data != targetValue) // no match
{
if(nullptr != next) // more elements?
retVal += next->countTV() // continue recursive count
}
else
{
std::cout << "Found match" << std::endl; // for diag only
retVal += 1; // because 1 match has been found
if(nullptr != next) // more elments
retVal += next->countTV(); // continue recursive count
}
return (retVal); // always return value from each level
}

Issue with recursive function C++

I have a short recursive function to write, and I am having an issue with my function returning seg fault 11 when I run it through g++. I am pretty bad at recursion, and just starting to learn it. Please let me know if you have any suggestions! The goal is to count how many nodes have a value larger than the inputed value "m" .Here is my code:
int LinkedList::countOccurrencesMoreThanRec(int m)
{
// first do the base cases that do not require recursion
if (head == NULL)
return -1;
int answer = 0;
if ((head -> getNext()) == NULL)
{
if ((head -> getValue()) > m)
answer ++;
return answer;
}
// if none of those were true, call the recursive helper method
Node *BatMan = head;
answer = countOccurrencesMoreThan(BatMan, m);
return answer;
}
/* countOccurrencesMoreThan
*
* private recursive method.
* TODO: fill in this method
*/
int LinkedList::countOccurrencesMoreThan(Node *h, int m)
{
// check for the base case(s)
int answer = 0;
if ((h -> getNext()) == NULL)
{
if ((h -> getValue()) > m)
answer++;
return answer;
}
// smaller case
Node *Bane = h;
answer = countOccurrencesMoreThan(Bane, m);
return answer;
// general case
}
Your comments are lying.
// smaller case
Node *Bane = h;
Here, you're setting Bane to the same value that was passed in to your function. You're not actually testing the next item in the list, you're doing the same list again.
This isn't the only problem in your code, but it will at least help with the question you asked.
One of the first questions with recursion should always be, do I need recursion? When iterating elements of a LinkedList there is absolutely no need to recurse.
Secondly, I strongly advise against rolling your own linked list class as the time it takes to write your own would be better spent learning libraries such as the STL which give you great data structures out of the box for free (that other colleagues understand!).
However to accomplish what you are trying to achieve recursively, you could either make the "answer" int a class member, a global variable (shudder) or pass the answer to each invocation of the function (passing zero in the first instance), but I cannot stress enough that the recursive approach is not the right approach for this problem. The answer variable has no place in a LinkedList class for a start, global variables are almost always evil, and passing around a value you're simply incrementing is inefficient and confusing.
int LinkedList::countOccurrencesMoreThan(Node *h, int m, int answer)
{
if( h->getValue() > m ) {
++answer;
}
if (h -> getNext() == NULL)
{
return answer;
}
countOccurrencesMoreThan( h->getNext(), m, answer);
}
Here is a better non recursive implementation with a simple LinkedList class:
void LinkedList::countOccurrencesMoreThan(int value) {
Node* node = this->head;
int occurrences = 0;
while(node != NULL) {
if( node->getValue() > v ) {
++occurrences;
}
node = node->getNext();
}
std::cout << "occurrences = " << occurrences << std::endl;
}