operator [ ] recursion - c++

I need help creating a recursive definition for operator [] for a linked list.
LN has a int value and a next pointer
int & operator[] (int i, LN*l, int &k){
int k = 0;
//check if list is empty
if(l == 0)
return -1;
//base case
if(k == i)
return l->value;
else
//I need to traverse through the linked list until I reach the ith position
return operator[](i, l->next, ++k);
}
Am I on the right track? Is there a way I could eliminate the k variable?
//make this a member function
Assuming that there is a private LN* head
int & operator[](int &i){
{
LN* temp = head;
if(i < 0 || temp ==0)
return -1;
if(i == 0)
return temp->value;
else{
temp = temp->next;
return operator[](--i);
}
}

You could get rid of k (both the parameter and the local variable), by passing i-1 in your recursive call along with l->next. Then when i is 0 you know you want the current item.
return operator[](i-1, l->next);
You should also add some checks to make sure i isn't less than zero.
Also note - recursion isn't really helping here, you could more easily do this in a loop.

I'd rewrite it as:
int & operator[] (int i, LN* l){
if(i == 0) return l->value;
else return operator[](i - 1, l->next);
}
that is: decrement the i variable until we reach 0 (that means we have moved to the next i times).
Also if you want the syntactic sugar that is list[i] you should make this a member function of your list class.
On a side note you should use std::list<int> or std::forward_list<int> instead of creating your own implementation.
Finally you should notice that linked-lists, in general, are really not meant to be randomly accessed. You should an array based container instead.

Related

Recursively traverse dictionary trie to count total words

I've built a trie from a linked list. Each node contains a char and an array of 27 nodes (letters of the alphabet + an extra spot for $ to represent the end of a word).
I tried writing a recursive method to count the number of words but it is returning 1. I'm not sure how to fix it or exactly what is wrong.
int recursiveCount(Node* temp, int count)
{
if (temp->value == '$')
{
count++;
}
for (int i = 0; i < 27; i++)
{
if (temp->array[i] != NULL)
{
return recursiveCount(temp->arr[i],count);
}
}
return count;
}
You pass count by value which means that it goes out of scope when the recursion unravels and only the one "furthest" out gets returned and since that i s the first count to be incremented it is just 1. Pass by reference instead int recursiveCount(Node* temp, int& temp);
As already noted in the other answers, your issue is that you're having different count variables, one for each recursive call. Incrementing one won't change the others. Instead of passing a (non const) reference you can also go for a more functional programming approach and return the count from your function. Of course you then need to sum up the returned counts of all recursive calls you made:
unsigned recursiveCount(Node const * node) /* you don't change the node, so make
it const. Why a pointer btw? A
reference would do fine! */
{
unsigned count = 0; /* You aren't expecting a negative number of
words, are you? So use unsigned. */
if (node->value == '$')
{
count++;
}
for (int i = 0; i < 27; i++)
{
if (node->array[i] != NULL) /* "array"!? change that to a meaningful
name ... "children" is bad, but not as
bad as "array" ... */
{
count += recursiveCount(node->array[i]); /* "arr" was a typo I
suppose */
}
}
return count; /* consistent indentation, please! */
}
You have marked this as C++, so I'm puzzled why the method is not part of Node. See encapsulation.
The significant error in your recursion code is not adding every '$'s found in each subsequent node. In particular, your code returns the count of only one invocation of the for loop, all others are discarded.
for (int i = 0; i < 27; i++)
{
if (temp->array[i] != NULL)
{
return recursiveCount(temp->arr[i],count);
// This only returns one value,
// and ignores all the other 26 possible values
// these should sum together
}
}
Consider making the method part of the node. Note how retVal accumulates every '$' found.
int Node::recursiveCount()
{
int retVal = 0; // accumulation
if (value == '$')
{
retVal += 1; // 1 word found here
}
// keep searching here, there might still be words with prefix
for (size_t i = 0; i < 27; i++)
{
if (nullptr != nxt[i])
{
retVal += (nxt[i]->recursiveCount());
// ^^ accumulate any other words found
}
}
return (retVal); // return full count
}

Finding smallest subsequence of an array

I have an array e.g. {1,2,4,5,6}. I want my function to find biggest possible number X such that all numbers from 1,2,...,X-1 are in the array. In this case X=3. Numbers in an array could be from 0 to infinitty.
My attempt is:
int array(int* t, int r) {
int* a;
int m=0;
int i;
for(i=0;i<=r;i++){
a[i]=i;
if(a[i]==t[i])
m++;
}
return m;
}
I wanted to create an array from 1 to r, which is the length of an array, full of natural number i.e. {1,2,3...} . Then i wanted to compare it with the actual array t. If there is a match look for another one.
I have no idea why it does not work and how to fix it?
Anyway code does not work and i still have no idea how to fix this.
Still looking for an answer.
Update: I did something like:
int array(int* t, int r) {
for(int x=0;x<r;x++){
for(int y=0; y<r-1;y++){
if(t[y]>t[y+1]){
int temp=t[y+1];
t[y+1]=t[y];
t[y]=temp;
}
}
}
for (int i = 0; i != r; i++) {
if (t[i] != (i + 1)) {
return i + 1;
}
}
return r + 1;
}
However when in input array i have zero at some place e.g. {5,0,1,2} the function always, regardless of where the zero is placed returns 1. Why is that?
There are a number of issues with your code
int array(int* t, int r) {
int* a;
int m=0;
int i;
for(i=0;i<=r;i++){
a[i]=i;
if(a[i]==t[i])
m++;
}
return m;
}
a is uninitialized, i.e. it does not point to valid memory allocated by your program. You need to do int *a = new int[r]. Don't forget to do delete a before your function returns
i should go up to r - 1 not r. So i < r rather than i <= r
Here is some pseudocode which outlines a possible method of solving this. The result is zero if it couldn't find a valid range to start from.
Pseudocode (Fast, thanks to Kenny Ostrom)
let curr = 0
let lookup = std::unordered_set<int>
insert all your elements into lookup
Starting from 0 to n where n is the size of your array of elements
[Loop]
If curr + 1 is not in lookup break out of loop
Else set curr to curr + 1
[Loop End]
Finally return curr + 1
Pseudocode (Kinda fast depending on your sorting algorithm)
Sort the array (std::sort is always a good option)
Set some variable curr to 0
Starting at a0 to an, where ai is an element of your array at index i
[Loop]
If curr + 1 is not equal ai then break out of the loop
Else set curr to ai
[Loop End]
Finally return curr + 1
Pseudocode (Slow)
Set some variable curr to 0
Starting at a0 to an, where ai is an element of your array at index i
[Loop]
Starting at aj to an where j = 0
[Loop]
If curr + 1 is equal to aj then set curr to aj and break out of this loop
[Loop End]
If curr did not change, then break out of this loop
[Loop End]
Finally return curr + 1
You don't need extra array, you may just iterate until index mismatch your expectation:
int find_iota_end(const int* a, int size)
{
std::sort(a, a + size); // if initial array is not sorted.
for (int i = 0; i != size; ++i) {
if (a[i] != (i + 1)) {
return i + 1;
}
}
return size + 1;
}
Upon reflection, I think your original idea was pretty close to a good algorithm, if you fix the bugs, and completely ignore any value a[i] where that value is not in the range [1..r].
You must allocate actual memory for your second vector, and you need two independent loops. The first loop fills in the second vector, if the value is relevant. The second loop looks for the answer.
This gives you space O(n) because you only consider that many possible answers, and time O(n) because it just reads through length, twice.

How can I add two values in a list in C++ using rbegin() and advance(iterator,1)?

I'm trying to calculate the fibonacci series using a list in C++, as instructed.
I was left with notes on how to improve it, and I simply don't understand what is being asked of me. How can i use rbegin() and advance(iterator,1) to add previous values and calculate a new one?
Here is what I had earlier.
list mutableFibonacci(int position)
{
list<int> series;
int first = 0; //Remove
int second = 1; //Remove
for (int i = 1; i <= position; i++)
{
if (i == 1)
series.push_back(1);
else
{
//We can get the last value and the value before from the series, like so, series.rbegin(); then get the value from the reverse iterator. Then we can call advance(iterator, 1) to get to the previous value. We can get the second to last value.
series.push_back(first + second);
first = second;
second = series.back();
}
}
return series;
}
Here is what I tried to do to fix it.
for (int i = 1; i <= position; i++)
{
if (i == 1)
series.push_back(1);
else
{
int last = series.rbegin();
int previous = advance(series, 1);
series.push_back(last + previous);
}
}
return series;
series.push_back(1);
series.push_back(1);
for (int i = 3; i <= position; ++i){ //First 2 elements inititalised
list<int>::reverse_iterator it = series.rbegin(); //End of the list
list<int>::reverse_iterator it2 = it; //Copy the iterator
advance(it2,1); //Move the iterator
series.push_back(*(it)+*(it2)); //Add the sum
}
Without the int it can look like this. The auto from before is a C++11 shortcut to defining types for variables (thus instead of having to type list<int>::reverse_iterator I can type auto)
First of all your initialization is incorrect, you need to initialize at least 2 elements, or std::advance() would have Undefined Behaviour:
if (i < 3)
series.push_back(1);
rbegin() will give iterator (in this case reverse one), not int, which semantically behaves like a pointer:
list<int>::reverse_iterator it = series.rbegin();
int last = *it;
std::advance( it, 1 );
series.push_back( last + *it );
not sure, why std::advance() is recommended, std::next() would fit better here.

Remove element from a list in C++

I am working on an exercise in C++ and I am trying to understand how to remove an element from a list and shift the rest to the left. I wonder if there is a neat solution. Here is my version, it seems to do the job, but I have a feeling there is a better way:
Account AccountList::remove(int i){
if(i>=0 && i<size()) {
for (int n = i; n < size(); n++) {
if(i+1!=size()) {
aList[n]=aList[n+1];
}
}
sz--;
return aList[i];
} else {
return Account();
}
}
You have two issues in this.
You are not returning the removed element, instead overwriting it with the next element and returning that one. I don't think this is your intention.
Your loop range is not right. With this loop, you will go past the array bounds with the index n+1 when n = size() - 1
The corrected one is given below.
Account AccountList::remove(int i)
{
if(i>=0 && i<size())
{
Account a = aList[i]
for (int n = i; n < size() - 1; n++)
{
if(i+1!=size())
{
aList[n]=aList[n+1];
}
}
sz--;
return a;
} else
{
return Account();
}
}
If you're doing this, you're not implementing the list correctly. A list should have complexity O(1) for removing an element. That looks more like an array or a vector.
A list typically consists of nodes linked to each other, in which case you'd only need to delete the node in question and make the previous node point to the node after the one you're deleting.

binary heap - how and when to use max-heapify

i'm reading about the heap data structure, and i can't figure out when to use max heapify function and why.
I wrote a insert function that will always keep the heap a max-heap and i can't see when will max-heapify ever be used.
Can you please explain?
Thank you
this is my code:
int PARENT(int i) {
return i/2;
}
int LEFT(int i) {
return 2*i;
}
int RIGHT(int i ) {
return 2*i +1;
}
void max_heapify(int *v, int index, int heapsize) {
int largest;
int left = LEFT(index);
int right = RIGHT(index);
if (left<heapsize && v[left] > v[index])
largest = left;
else
largest = index;
if (right < heapsize && v[right] > v[largest])
largest = right;
if (largest !=index) {
v[index] = v[index] ^v[largest];
v[largest] = v[index] ^v[largest];
v[index] = v[index] ^v[largest];
max_heapify(v,largest,heapsize);
}
}
void insert(int *v, int * length, int value) {
v[++*length] = value;
int valuePos = *length;
int parent = PARENT(valuePos);
if (parent!=valuePos) {
while (v[parent] < v[valuePos]) {
v[parent] = v[parent] ^ v[valuePos];
v[valuePos] = v[parent] ^v[valuePos];
v[parent] = v[parent] ^ v[valuePos];
valuePos = parent;
parent = PARENT(valuePos);
}
}
}
The heapify algorithm should be used when turning an array into a heap. You could do that by inserting each array element in turn into a new heap, but that would take O(n lg n) time, while heapify does it in O(n) time.
max_heapify is expected to invoke on a regular array, to make it a heap. And insert does the maintenance work, which requires the array (v in your function) already being a heap.
The max-heapify function, as you call it, is a general heapify function (a heap can use any valid comparison function for sorting it's elements). It is intended to be used as an init function for constructing a heap from an array.
The complexities of functions for dealing with a heap (with their intented usages):
init (max-heapify): O(n) , used to initialize a heap from a sorted sequence (array) (max-sorted, in your case)
insert : O(lg n) , used to insert a single element in a heap (maintains the heap tree "sorted")
delete : O(lg n) , used to remove a "best" (max, in your case) element from a heap (maintains the heap tree "sorted")
But, since this question is tagged C++, you should also consider using a std::set from STL instead of implementing your own heap. Complexities of the considered operations are the same as for any heap implementation, and it can easily operate with any comparison function (either pre-written or user-written). Another advantage against a heap implementation is that it is a sorted container, and you can easily iterate trough all the elements in the sorted order (not just the first one) without destroying the structure.
The only problem with std::set is that it is a unique container - meaning, only 1 copy of an element with a same key can exist in it. But there is a solution for that also - std::multiset keeps sorted instances of multiple objects with the same key.
Also, depending on your required usage (it there is a lot of data associated with the search key), you might also want to try std::map or std::multimap.
If you want to make your own heap implementation, I would strongly suggest putting it in a separate class (or even a namespace) if your intention is to use C++ to the fullest. If you just intend to keep the implementation in the form it is, you should consider re-tagging the question to C
You need to insert the data in heap randomly like in array. Afterwards u can call the max heapify function to keep the property of a Max Heap. Here is my code
class max_heap{
private: // are the private members of class
int *arr;
int size;
int ind;
};
void max_heap::bubbledown(int *ar, int i)
{
int len = ind - 1;
int lt = 2 * i;
int rt = lt + 1;
while (lt <= len && rt <= len)
{
if (arr[i] > arr[lt] && arr[i] > arr[rt])
break;
else if (ar[lt] > ar[rt])
{
if (ar[i] < ar[lt]){
swap(ar[i], ar[lt]);
i = lt;
lt = 2 * i;
}
}
else if (ar[lt] < ar[rt])
{
if (ar[i] < ar[rt]){
swap(ar[i], ar[rt]);
i = rt;
rt = (2 * i)+1;
}
}
}
}
void max_heap::heapify()
{
int len = ind - 1;
for (int i = len; i >= 1 && (i/2) >= 1; i--)
{
if (arr[i] > arr[i/2])
{
swap(arr[i], arr[i/2]);
bubbledown(arr, i);
}
}
}