Java PriorityQueue implementation: Why Object[] queue instead of E[] queue? What's the purpose of "key" in siftUp/siftDownComparable? - heap

I'm studying the JDK implementation of PriorityQueue.
1) The entire queue is stored in
transient Object[] queue;
Why not declare the array using the generic E? (Instead, there's a lot of casting E to objects in the class.)
2) The first line of the siftUpComparable/siftDownComparable methods is
Comparable<? super E> key = (Comparable<? super E>)x;
Is this a guard clause to verify that x is comparable? (Otherwise, why not just use x directly?)
Here's the entire method:
private void siftDownComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>)x;
int half = size >>> 1; // loop while a non-leaf
while (k < half) {
int child = (k << 1) + 1; // assume left child is least
Object c = queue[child];
int right = child + 1;
if (right < size &&
((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
c = queue[child = right];
if (key.compareTo((E) c) <= 0)
break;
queue[k] = c;
k = child;
}
queue[k] = key;
}

1) You cannot instantiate an array of a generic type without having a reference to the Class of the object. See JavaDevil's comment below for an example. However, by creating an array of Object's instead, there's is no requirement to feed an instance of the Class to the PriorityQueue.
E[] array = new E[10]; // won't compile
2) A PriorityQueue can sort its elements either by a Comparable's object compareTo() method or using a Comparator for objects that are not necessarily Comparable. The siftDownComparable method is only invoked if a Comparator was not provided when the PriorityQueue was created. Since the type parameter does not stipulate that <E extends Comparable>, you need to cast it explicitly. Here's the siftDown() method.
private void siftDown(int k, E x) {
if (comparator != null)
siftDownUsingComparator(k, x);
else
siftDownComparable(k, x);
}

Related

How to assign a pointer to object to another pointer to object of same class?

I have a class called arr and it has a function named _union written like this:
template<class T>
arr<T> *arr<T>::_union(arr<T> B) {
arr<T> *C(this->length + B._length());
bool isPresent = false;
for (int i = 0; i < length; i++)
C->push_back(this->get(i));
for (int j = 0; j < B._length(); j++) {
for (int k = 0; k < C->_length(); k++) {
if (B.get(j) == C->get(k))
isPresent = true;
}
if (!isPresent)
C->push_back(B.get(j));
isPresent = false;
}
return C;
}
The function returns a pointer of an object that was newly created inside this function's scope.
In main function, I wrote code like this :
arr<int> *a3 = a1._union(a2);
a3->display();
When I run, this gives me an error:
What is the problem here? If I don't use any pointers and just return normal object then everything is fine.
Please help me. Also I don't have any copy constructers inside the class. I am just trying to create my own array class with data and functions.
In this code
arr<T> *C(this->length + B._length());
C is a pointer and this->length + B._length() is an integer, hence the error. You can't assign an integer to a pointer.
I guess you were trying to write this code
arr<T> *C = new arr<T>(this->length + B._length());
This code allocates a new arr<T> object using new and calls the a constructor for that object using the integer parameter this->length + B._length().
However is usually a bad idea to use dynamic allocation like this. You should think about redesigning your function without using pointers.
template<class T>
arr<T> arr<T>::_union(arr<T> B) {
arr<T> C(this->length + B._length());
...
return C;
}
This will require you to define a copy constructor etc for arr<T>. But that is normal C++ programming you shouldn't be reluctant to do it.

How to clone objects of unknown dynamic type in C++?

I want to build an array of dervied class objects. I have this base class:
class CandyBox {
protected:
string flavor;
string origin;
public:
inline CandyBox();
inline CandyBox(string s1, string s2);
virtual float getVolume() = 0;
virtual void toString();
CandyBox& operator=(const CandyBox& obj);
virtual ~CandyBox() {}
};
And 2 derived class named class Lindt and class ChocAmor with constructors and methods as well. I'm trying to build now a scratchy list like this:
CandyBox** vec = new CandyBox*[n];
for (int i = 0; i < n; i++) {
cin >> type;
if (strcmp(type, "ChocAmor") == 0) {
vec[i] = new ChocAmor(1, "s", "ro");
}
else vec[i] = new Lindt(1, 2, 3, "f", "it");
}
My question is: What if I want to make another class named CandyBag that contains an attribute like this one CandyBox** vec = new CandyBox*[n]; and I need this method:
CandyBag& operator=(const CandyBag& candy) {
ChocAmor::operator=(candy);
Lindt::operator=(candy);
dim_max = candy.dim_max;
current_dim = candy.current_dim;
vec = new CandyBox*[candy.dim_max];
for (int i = 0; i <= current_dim; i++) {
vec[i] = new ; //HERE I'M STUCK
// because I can't just simply write vec[i] = candy.vec[i], right?
// I need to allocate memory for that vec[i] first
}
return *this;
}
I'm not sure how can I allocate memory for that vec[i] if I don't know the type (if it's a ChocAmor object or a Lindt type in that candy.vec[i]). Should I get an auxiliar array where I should store the types of that array?
All pointers to class-type are the same size and representation. That is essential for opaque pointers to work at all.
If you want to enable cloning the pointed-to objects, add a virtual .clone() to the interface, and/or write your own copying smart-pointer.
Lugging around a pointer to a clone-function or maintaining a mapping from typeid to clone-function would be far more cumbersome, though can be the right solution in other circumstances.
Otherwise, I have a suggestion:
Use smart-pointers, preferably std::unique_ptr, and standard containers, preferably std::vector, to avoid manual memory-management and gain all the associated benefits of using standard types.

How to erase a certain element from a shared_ptr to a vector of objects?

I have created a member variable (in the class Group) that is a shared_ptr to a vector (called members that stores objects of type User (a different class). Here is the member variable definition (empty):
std::shared_ptr <std::vector<User>> members = std::make_shared<std::vector<User>>();
To eliminate a certain User object from the vector (members), I created a member function (remove) inside the class Group. It checks all the User objects inside the vector and, when encounters the one with the a.URI value that is looking for, it erases the object at that location in the vector.
void Group::remove(User a) {
for (auto i = 0; i < members->size(); i++){
if (a.URI == (*(members->begin()+i)).URI) members->erase(*(members->begin() + i));
}
That is my remove function by now, but it doesn't work. I have checked different configurations but can`t make it work. Is there a problem with my function? How should this function be implemented (special rules for shared_ptr?)? Is there a better/optimal way?
I think no more code is needed here to solve my question. However, for those who want a MCV example, I tried to write one here (Ideone).
Firstly, std::vector::erase expects an iterator as its argument, so change
members->erase(*(members->begin() + i))
to
members->erase(members->begin() + i)
Secondly, after the element being erased, when i++ is evaluated, you will skip the next element or get out of the bound of the vector. You might change the loop to
for (auto i = 0; i < members->size(); ) {
if (a.URI == (*(members->begin()+i)).URI)
members->erase(members->begin() + i);
else
i++;
}
Why don't you declare the vector members as static member of the group class. I did it like this:
#include <bits/stdc++.h>
using namespace std;
class User{
public:
int URI;
User(int a){
URI = a;
}
};
class Group {
public:
static vector<User> members;
void remove(User a) {
for (int i = 0; i < members.size();){
if (a.URI == (*(members.begin()+i)).URI) members.erase((members.begin() + i));
else
i++;
}
}
Group(User a, User b, User c){
members.push_back(a);
members.push_back(b);
members.push_back(c);
}
};
vector<User> Group::members;
int main() {
User a(1), b(2), c(3);
Group obj(a, b, c);
obj.remove(a);
return 0;
}
Hope it helps.

Consruct Member Class using Data computed in Composing Class

I have a class Itch that is a member of the class Scratch. I want to do some computations in the Scratch constructor and pass the result of these computations to instantiate the Itch object. My best guess in doing this is below, but this returns garbage:
#include <iostream>
class Itch {
public:
int N;
Itch(int n) {N = n;}
};
class Scratch {
private:
int N;
public:
Itch it;
Scratch(int n);
};
Scratch::Scratch(int n) : it(N) // here is where I want to use new data
{
// do some silly things
int temp = 5;
temp += n + 45;
N = temp - 1;
}
int main() {
int n = 1;
Scratch sc(n);
std::cout << sc.it.N << "\n";
}
Is there a standard way to do this?
The things in the initializer list happen before the things in the constructor code. Therefore, you cannot affect anything in the initializer list with the code in the constructor. You have a few options.
A reasonable approach would be to have an Itch * member rather than an Itch, and initialize it when it's ready, e.g.:
class Scratch {
...
Itch *it;
...
};
Scratch::Scratch(int n) : it(NULL)
{
// do some silly things
int temp = 5;
temp += n + 45;
N = temp - 1;
it = new Itch(N); // <- now you have enough info to instantiate an Itch
}
And you'll have to remember to clean up in the destructor unless you use an auto_ptr:
Scratch::~Scratch () {
delete it;
}
Another reasonable approach would be to pass n to the Itch constructor and have it do the calculations there instead of in Scratch, perhaps even allowing Itch to determine N, e.g.:
class Itch {
private:
int N;
public:
Itch (int n);
int getN () const { return N; }
}
Itch::Itch (int n) {
// do some silly things
int temp = 5;
temp += n + 45;
N = temp - 1;
}
Scratch::Scratch (int n) : it(n) {
// you can either remove Scratch::N altogether, or I suppose do:
N = it.getN();
// ... do whatever makes sense, try not to have redundant data.
// (also ask yourself if Scratch even *needs* to know N, or at
// least if it can just use it.getN() everywhere instead of
// keeping its own copy.)
}
Another approach, which IMO is a bit odd but it's still possible in some situations, is to have e.g. a static function (member or not) that computes N from n, which you can use in the initializer list, e.g.:
static int doSillyThings (int n) {
int temp = 5;
temp += n + 45;
return temp - 1;
}
Scratch::Scratch(int n) : N(doSillyThings(n)), it(N)
{
}
Choose whichever leads to the cleanest, most maintainable and easy-to-read code. Personally I'd prefer the first, Itch * option, since it makes logical sense and is very clear: You do the calculations necessary to initialize the Itch, then you initialize it.
You should think about your code a bit. If the Scratch's N is always equal to it.N, then do you really need both Ns?
There are other options too (including restructuring your code completely so you don't have to have an Itch member of Scratch, or so that you don't have to have it depend on extra calculations done on the Scratchs constructor parameters but that really depends on the situation), but hopefully that inspires you a little.
The reason your code returns garbage, by the way, is because N is garbage at the point you pass it to the Itch constructor. It's uninitialized until you initialize it, and at the point where it(N) is you haven't initialized N yet.

Making an object belonging to a class depending on input parameters in C++

I'm trying to build an object which is of a type which depends on input parameters. E.g. my object is called 'process' and at runtime an integer between 2 and 5 (inclusive) is entered and something a bit like this would happen:
if (input == 2) TwoJ process;
if (input == 3) ThreeJ process;
if (input == 4) FourJ process;
if (input == 5) FiveJ process;
Obviously the above will not work because the object goes out of scope immediately. Is there a way to implement this nicely?
Cheers
Use a factory function that returns a smart pointer to a base Process class and whose implementation is determined by an integer value supplied to the factory function (requires that all classes have a common base).
For example:
class Base_process
{
public:
virtual ~Base_process() {}
virtual void do_something() = 0;
};
class TwoJ : public Base_process
{
public:
void do_something() {}
}
class ThreeJ : public Base_process
{
public:
void do_something() {}
}
std::unique_ptr<Base_process> make_process(int a_type)
{
if (a_type == 1) return std::unique_ptr<Base_process>(new TwoJ());
if (a_type == 2) return std::unique_ptr<Base_process>(new ThreeJ());
// Report invalid type or return an acceptable default if one exists.
throw std::invalid_argument("Unknown type:" + std::to_string(a_type));
}
A factory method of sorts
std::unique_ptr<ProcessType> CreateProcess(int input){
if(input == 2) return std::unique_ptr<ProcessType>(new TwoJ());
.....
}
This assumes, of course, that the various classes you use have a common base class, here ProcessType, and that you are satisfied with interacting with it via a base class pointer.
you can but, you need 1 base class for those all e.g.
Base* process;
if (input == 2) process = new TwoJ();
if (input == 3) process = new ThreeJ();
then to access those class all you need is:
if (input == 2) (TwoJ*)process->someTwoJMethod();
or by using dynamic_cast:
TwoJ* p = dynamic_cast<TwoJ*>(process);
if(p != 0) {
p->someTwoJMethod();
}
with this you own responsibility to delete your object once it's go out of scope.
The previous answers are the best way in cpp using std::unique_ptr the object will get deleted automatically when the object go out of scope.