d-max heap insert items from the top and down - c++

I want to implement an insert function in c++ to build a d-max heap. The d is referring to the number of children in the heap and a max heap is a heap which has its' elements structured in a priority (3,2,1...). The heap is supposed to be represented as an array and the function I'm looking for is adding items from the top one by one and then continuing downward. This may seem like an easy task but I'm confused about how this is going to work.
Here is a rough example of the template function:
template <typename Comparable>
void buildHeapTopDown(Comparable arr[], int size, int d)
{
for (int i = 0; i < 5; ++i)
{
arr[0] = 2;
arr[1] = 3;
arr[2] = 4;
arr[3] = 6;
arr[4] = 9;
}
}
Now as this is some really basic code the function is not really informative about the way a d-heap works. What I mean is I have not implemented the theory behind the d-heap, which basically is pretty much the same as the theory behind a binary heap (we only replace 2 with d in the formulas). The formulas for finding a parent and a child for a heap then becomes:
(x-1) / d, x*d + 1 (left child) and x*d + 2 (right child).
I also know there is a way to create a heap using the <algorithm> class, but as these functions are already prepared and they are using vectors, it's not really what I'm looking for.
Example using the algorithm class:
#include <iostream>
#include <array>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int myInts[] = { 1, 2, 3, 5, 4, 7, 10, 13, 15, 6, 8, 17, 9, 11, 9 };
vector <int> v(myInts, myInts + 15);
make_heap(v.begin(), v.end());
cout << "Initial max heap: " << v.front() << endl;
pop_heap(v.begin(), v.end());
v.pop_back();
cout << "Max heap after pop: " << v.front() << endl;
v.push_back(77); // insert example
push_heap(v.begin(), v.end());
cout << "Max heap after push: " << v.front() << endl;
sort_heap(v.begin(), v.end());
cout << "Final sorted range:";
for (unsigned i = 0; i < v.size(); i++)
{
cout << " " << v[i];
}
cout << endl;
getchar();
getchar();
}
Anyone who can give any hints how to do it as the way I described in the top?

Related

Implement a function that prints an array using pointers

I need to print an array by implementing the use of a function before the main function. So I tried the following function:
int* printArr(int* arr)
{
for (int i = 0; i < 5; i++) {
cout << arr[i];
}
return arr;
}
I encountered two problems when implementing this into the whole code.
First, this is printing what I think is the address of the array and not the actual array. Pretty sure this is because of the return arr; in line 10. But if I do not write return then the code will produce an error. How can I fix this?
Second, I do not understand the second argument printArr has. In line 19, you can see cout << printArr(arr, 5) << endl;. How come there is a single numeric value, that one being 5 in this case, as an argument? How can I account for this in my function?
Please keep in mind that I am new to C++ and coding in general. Also, this code was given to me, hence why I do not understand certain aspects of it.
This is my code so you can see what I mean:
#include <iostream>
using namespace std;
// Declare function printArr here
int* printArr(int* arr)
{
for (int i = 0; i < 5; i++)
{cout << arr[i];}
return arr;
}
int main()
{
int arr[5] = {1, 3, 5, 7,9};
int last_num = arr[sizeof(arr)/sizeof(int)-1];
cout << "Before reversing" << endl;
cout << printArr(arr, 5) << endl;
// reverse "arr" using reference(&)
cout << "After reversing" << endl;
printArr(arr, 5);
return 0;
}
The declaration and implementation of printArr() is all wrong.
First, this is printing what I think is the address of the array and not the actual array.
The printArr() function itself is printing the contents of the array (well, the first 5 elements anyway), and then returning the address of the array. It is main() that is printing that address afterwards, when it passes the return value of printArr() to std::cout <<.
Pretty sure this is because of the return arr; in line 10. But if I do not write return then the code will produce an error. How can I fix this?
By getting rid of the return type altogether. There is no good reason to return the array pointer at all in this example, let alone to pass that pointer to std::cout. So printArr() should be returning void, ie nothing.
Second, I do not understand the second argument printArr has. In line 19, you can see cout << printArr(arr, 5) << endl;. How come there is a single numeric value, that one being 5 in this case, as an argument?
Because main() is passing in the element count of the array (5) so that printArr() can know how many elements to actually print, instead of hard-coding that value in the loop. However, your declaration of printArr() does not have a 2nd parameter with which to accept that value, that is why you are getting errors.
How can I account for this in my function?
By adding a 2nd parameter in the function declaration, eg:
#include <iostream>
using namespace std;
// Declare function printArr here
void printArr(int* arr, int size)
{
for (int i = 0; i < size; i++)
{
cout << arr[i] << ' ';
}
cout << endl;
}
int main()
{
int arr[5] = {1, 3, 5, 7, 9};
const int count = sizeof(arr)/sizeof(arr[0]);
int last_num = arr[count-1];
cout << "Before reversing" << endl;
printArr(arr, count);
// reverse "arr" using reference(&)
cout << "After reversing" << endl;
printArr(arr, count);
return 0;
}
Live Demo

Difference betwen string and int when using std::allocator C++

I'm trying to learn how std::allocator works and I tried to do a simple task. The task is to delete for example the second element and to shift the elements to the left when the elements has been deleted.
For example, we have this as an input array: 1,2,3 and the output should look like 1,3. And what I get as input is: 1,3,3
This thing doesn't happen and that's why I'm here asking you.
But, when I have **std::allocator<string> myVar** instead of **std::allocator<int> myVar** it works.
Then the input: one, two, three and output is: one, three
Here's the code using std::allocator<int>:
#include <iostream>
#include <memory>
using namespace std;
int main()
{
allocator<int> a1;
int* arr = a1.allocate(3);
for (int i = 0; i < 3; i++)
a1.construct(arr + i, i + 1);
a1.destroy(arr + 1);
a1.construct(arr + 1, 3);
for (int i = 0; i < 3; i++)
cout << arr[i] << " ";
cout << endl;
a1.deallocate(arr, 3);
return 0;
}
And here's the code with std::allocator<string>:
#include <iostream>
#include <memory>
#include <string>
using namespace std;
int main()
{
allocator<string> a1;
string* wrd = a1.allocate(3);
a1.construct(wrd, "one");
a1.construct(wrd + 1, "two");
a1.construct(wrd + 2, "three");
a1.destroy(wrd + 1);
cout << wrd[0] << " " << wrd[1] << " " << wrd[2] << endl;
a1.deallocate(wrd, 3);
return 0;
}
When you call allocator::destroy, it just destroys the object in the memory -- it doesn't do anything to the memory (its still there) or move anything. When you later try to do somthing with that memory, you get undefined behavior, but in the case of your strings, the "undefined behavior" turns out to be "act as if it was an empty string", so nothing gets printed.
If you were to call a1.construct(wrd+1, "three"); after the call to a1.destroy ins your string code (to make it the same as your int code), you would see it prints one three three

Lower bound error

I am following this tutorial on Lower_bound() in C++. I have made a simple code to find a number in a vector lesser than or equal to a number from the vector + any number that I want. My code goes like this
cout << *lower_bound(A.begin(), A.end(), A[x] + 3);
where the vector A[] is sorted. But the code points it to a number greater than the sum of both the numbers.
For example if my vector has values as 0, 3, 5, 8, 12 and I want it to print the nearest number lesser than or equal to A[3] + 3 = 11 it should give output as 8 but it gives the output of 12. Any reasons?
Here is my code:
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<int> A = {0, 5, 3, 12, 8};
sort(A.begin(), A.end());
cout << "A[3] = " << A[3] << endl;
cout << *lower_bound(A.begin(), A.end(), A[3] + 3) << endl;
return 0;
}
lower_bound
Returns an iterator pointing to the first element in the range [first,last) which does not compare less than val.
In your case it is not returning the last value less than 11. It returns the first value not less than 11, which in your example is 12.
If you want the largest number not greater than your target, you can use std::greater<> and reverse iterators (or sort by std::greater<>)
#include <vector>
#include <iostream>
#include <algorithm>
int main() {
std::vector<int> A = {0, 5, 3, 12, 8};
std::sort(A.begin(), A.end());
std::cout << "A[3] = " << A[3] << std::endl;
std::cout << *std::lower_bound(A.rbegin(), A.rend(), A[3] + 3, std::greater<int>{}) << std::endl;
return 0;
}

Reverse array with recursion C++

My main idea is to shrink they array from both sides . For example if the input is 1234 , wanna print 1234 and then 4321 (the reversed) .
#include <iostream>
#include <cmath>
#include <math.h>
using namespace std;
int reversedArray(int* x)
{
cout<< "*x out of while =" << *x <<endl ;
while( *x != 0 )
{
cout << "*x=" << *x << endl;
cout<< "====================== im in reversed =================" << endl ;
return reversedArray( x+1 );
}
cout<< "after return " << *x << endl;
}
int main ()
{
int Array[] = {10,2,3,4,8 ,0} ;
int* p_Array = Array;
reversedArray( Array );
}
After the "while" , why the functions that are in the stack, do not return to the next line ( " the --> cout<< "after return " <<*x <
void printReversed(int * x)
{
if (*x == 0) return;
std::cout << *x;
printReversed(x+1);
std::cout << *x;
}
The line:
return reversedArray( x+1 );
exits the function. So you never repeat the while or execute any of the code after the while if you go into the while. This makes the while effectively an if statement.
The code posted by Crazy Eddie does the job and Barmar explains the ineffectiveness of the while loop. I decided to post a non-recursive way to address the problem mentioned.
#include <iostream>
#include <vector>
using namespace std;
vector<int> reverseArray(vector<int>& arr) {
vector<int> ans;
int n = arr.size();
// insert all elements in the reverse order
for (size_t i = 0; i < n; i++) {
ans.push_back(arr[n-i-1]);
}
return ans;
}
int main ()
{
int array[] = {10, 2, 3, 4, 8, 0};
// convert into vector
vector<int> arr(array, array+6);
vector<int> rev = reverseArray(arr);
// merging the 2 arrays
arr.insert(arr.end(), rev.begin(), rev.end());
// printArray(arr) -- implement to fit your needs;
}
When you pass an int[] to a function it decays to an int* which is simply an address in memory. C++ a better plan would be to use copy_backward with an ostream_iterator:
copy_backward(Array, Array + sizeof(Array) / sizeof(*Array), ostream_iterator<int>(cout, " "))
Note that this method uses the actual size of the array, and does not depend upon a terminal element. Thus, no numbers are offlimits, and it's impossible to segfault by failing to provide the terminating element.
If you have access to C++11 you can simplify that a bit further to:
copy(crbegin(Array), crend(Array), ostream_iterator<int>(cout, " "))
Live Example

Array of int or vector?

i'm trying to store some elements that is going to change every time, but i don't know which
way is better and why. I'm thinking about two ways, 1) declaring array of int and loop or
use vector's.
Which way is better and why?
Does declaring array of int have any future memore problems as leak?
the code down below show the two ways i'm talking about:
1)
#include <iostream>
#include <vector>
int main()
{
int x[5];
x[0] = 10;
x[1] = 20;
x[2] = 30;
x[3] = 40;
x[4] = 50;
for(unsigned int i = 0;i<=sizeof(x[5]); i++)
{
std:: cout << "x[" << i << "] = "<< x[i] << std::endl;
}
system("pause");
return 0;
}
2)
#include <iostream>
#include <vector>
int main()
{
std::vector<int> x;
x.push_back(10);
x.push_back(20);
x.push_back(30);
x.push_back(40);
x.push_back(50);
for(unsigned int i = 0;i<=x.size()-1; i++)
{
std:: cout << "x[" << i << "] = "<< x[i] << std::endl;
}
system("pause");
return 0;
}
If this is all you have to do, and your array will always have a size that is known at compile time, then you do not need std::vector.
On the other hand, in C++11 you could use std::array instead of a plain C array (std::array is a zero-overhead, safer and more functional wrapper over a C array):
#include <iostream>
#include <array>
int main()
{
std::array<int, 5> x = { 10, 20, 30, 40, 50 };
for (unsigned int i = 0; i < x.size(); i++)
// ^^^^^^^^
{
std:: cout << "x[" << i << "] = "<< x[i] << std::endl;
}
}
Here is a live example. Notice, that std::array offers a size() member function which you may want to use instead of the sizeof operator.
Moreover, since std::array is a standard sequence container, you could iterate through its element this way:
std::size_t i = 0;
for (auto e : x)
{
std:: cout << "x[" << i++ << "] = "<< e << std::endl;
}
Here is a live example.
If the size is known at compile time, use std::array. If not, use std::vector. In either case, use iterators to look at the elements:
typedef std::array<int> my_container_type;
typedef my_container::iterator iterator;
my_container_type my_container = { whatever };
for (iterator it = my_container.begin(); it != my_container.end(); ++it)
std::cout << "x[" << (it - my_container.begin()) << "] = " << *it << '\n';
By using iterators you greatly reduce the risk of accidentally using a loop limit like sizeof(x[5]), which is nonsense.
Neither is "better". They both address entirely different use cases.
If you know the array size at compile time and are 100% sure it will never change, sure, use a plain old array. It has less overhead, and the compiler can even aid you with static analysis by spotting any attempts to read outside the boundaries.
On the other hand, if you are unsure of the array's side (i.e. you will be reading input from a file or the user), then use the std::vector. It can grow to any size to meet your needs.