My derived class merge_sort from dynamic_array does not have access to protected member T* array. Their are error everywhere it is used saying such.
I'm not sure why...except maybe the public designator for merge_sort should be something else?
#include "c_include.cpp"
using namespace std;
template <class T> class dynamic_array
{
protected:
T* array;
public:
int size;
void rorder();
void order();
void randorder();
void print_operator(ostream&)const;
dynamic_array(int sizein)
{
size=sizein;
array=new T[size]();
}
};
template <class T> void dynamic_array<T>::print_operator(ostream &os=cout)const
{
for (int i = 0; i < size; i++) os << array[i] << endl;
}
template <class T> void dynamic_array<T>::randorder()
{
srand(time(NULL));
int *ap;
for(ap=array;ap!=array+size;++ap){*ap=rand();}
}
template <class T> void dynamic_array<T>::order()
{
int *ap,i=0;
for(ap=array;ap!=array+size;++ap)
{
*ap=i;
++i;
}
}
template <class T> void dynamic_array<T>::rorder()
{
int *ap,i=size;
for(ap=array;ap!=array+size;++ap)
{
*ap=i;
--i;
}
}
template<class T> ostream& operator<<(ostream& stream, dynamic_array<T> const& data)
{
data.print_operator(stream);
return stream;
}
/*
Merge Sort
*/
template <class T> class merge_sort : public dynamic_array <T>
{
private:
const static int size;
int scratch[];
void flip_if_unordered(int &x, int &y)
{
if(array[x]>array[y])
{
int tmp=array[x];
array[x]=array[y];
array[y]=tmp;
}
}
void merge_algo(int &left, int &right_begin, int &right)
{
int iter,iter_left=left,iter_right=right_begin;
for(iter=left;iter<=right;++iter)
{
if( (iter_right>right) || ((iter_left < right_begin) && (array[iter_left]<=array[iter_right])))
{
scratch[iter]=array[iter_left];
++iter_left;
}
else
{
scratch[iter]=array[iter_right];
++iter_right;
}
}
for(iter=left;iter<=right;++iter){array[iter]=scratch[iter];}
}
void merge_recurse(int left,int right)
{
int left_end=(left+((right-left)/2));
int right_begin=left_end+1;
if(((left+1)==right)){flip_if_unordered(left,right);return;}
else if ((left==right)){return;}
else
{
merge_recurse(left,left_end);
merge_recurse(right_begin,right);
merge_algo(left,right_begin,right);
}
}
public:
merge_sort()
{
scratch = new T[size]();
if(scratch != NULL)
{
merge_recurse(0, size);
}
}
};
/*Quick Sort
void quick_sort()
{
quick_recurse(0,size);
}
void quick_recurse(int left, int right)
{
int l = left, r = right, tmp;
int pivot = array[(left + right) / 2];
while (l <= r)
{
while (array[l] < pivot)l++;
while (array[r] > pivot)r--;
if (l <= r)
{
tmp = array[l];
array[l] = array[r];
array[r] = tmp;
l++;
r--;
}
}
if (left < r)quick_recurse(left, r);
if (l < right)quick_recurse(l, right);
}
*/
Your base class depends on a template argument, so its type is a dependent type. The compiler won't know which specialization of the base class you use until is instantiated, so you have to help the compiler know that such identifier is a base's member. Either like this:
dynamic_array<T>::array
or
this->array
or
using dynamic_array<T>::array;
Related
I am trying to make a sorting function for a ring buffer class object, but it gives me the below error and I couldn't remove it:
template placeholder type 'ring' must be followed by a simple declarator-id
argument list for class template "ring" is missing
'arr' was not declared in this scope
(arr) was declared in the parameter of the function but yet it does not recognize it
hopefully someone can explain what is wrong with the sorting function, here is below my code:
#include<iostream>
#include<initializer_list>
template<typename T>
void swap(T& x, T& y) {
T temp;
temp = x;
x = y;
y = temp;
}
template<typename T>
class ring {
public:
class iterator;
public:
ring(std::initializer_list<T>elements) {
sze = elements.size();
value = new T[sze];
for (auto& i : elements) {
add(i);
}
}
T& get(int x) { return value[x]; }
std::size_t size() { return sze; }
void add(T v) {
value[index++] = v;
if (index == sze)
index = 0;
}
iterator begin() { return iterator(0, *this); }
iterator end() { return iterator(sze, *this); }
friend void BubbleSort(ring& arr, std::size_t n);
~ring() { delete[] value; }
private:
int index = 0;
std::size_t sze;
T* value;
};
template<typename T>
class ring<T>::iterator {
public:
iterator(int x, ring& y) :index(x), obj(y) {}
iterator& operator++() { index++; return *this; }
iterator& operator++(int x) { index++; return *this; }
bool operator!=(const iterator& other) { return index != other.index; }
T& operator*() { return obj.get(index); }
private:
int index;
ring& obj;
};
template<typename T>
void BubbleSort(ring& arr, std::size_t n) { // here is the function of the sorting.
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (arr.value[j] > arr.value[j + 1]) {
swap(arr.value[j], arr.value[j + 1]);
}
}
}
}
Your friendly compiler showed you already the problem and in which line it happened.
And it gave you 3 error messages telling you exactly what the problem is.
See my compiler output
Your class ring needs a template parameter. So same as in line 49 of the picture.
The below will compile.
#include<iostream>
#include<initializer_list>
template<typename T>
void swap(T& x, T& y) {
T temp;
temp = x;
x = y;
y = temp;
}
template<typename T>
class ring {
public:
class iterator;
public:
ring(std::initializer_list<T>elements) {
sze = elements.size();
value = new T[sze];
for (auto& i : elements) {
add(i);
}
}
T& get(int x) { return value[x]; }
std::size_t size() { return sze; }
void add(T v) {
value[index++] = v;
if (index == sze)
index = 0;
}
iterator begin() { return iterator(0, *this); }
iterator end() { return iterator(sze, *this); }
friend void BubbleSort(ring& arr, std::size_t n);
~ring() { delete[] value; }
private:
int index = 0;
std::size_t sze;
T* value;
};
template<typename T>
class ring<T>::iterator {
public:
iterator(int x, ring& y) :index(x), obj(y) {}
iterator& operator++() { index++; return *this; }
iterator& operator++(int x) { index++; return *this; }
bool operator!=(const iterator& other) { return index != other.index; }
T& operator*() { return obj.get(index); }
private:
int index;
ring& obj;
};
template<typename T>
void BubbleSort(ring<T>& arr, std::size_t n) { // here is the function of the sorting.
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (arr.value[j] > arr.value[j + 1]) {
swap(arr.value[j], arr.value[j + 1]);
}
}
}
}
I did not check the functionality. Sorting a ringbuffer sounds somehow strange . . .
In advanced, let me thank your for looking at this code for me, because it has been bugging me for a while now and I can't seem to find the issue.
Whenever I run it, it doesn't throw any errors within the console, instead it throws this error:
Debug Assertion Failed!
Program: [Filepath to .exe]
File: minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp
Line 892
Expression: is_block_type_valid(header->_block_use)
I've been trying to figure it out, but it just wont work for me. I believe it has something to do with the template types I am passing in, as it only crashes whenever I try to initialize a minHeap object or try my Push method, which I also believe is an issue.
Once again, thank you all so much for looking at my code.
Main:
#include "minHeap.h"
#include "Node.h"
#include <iostream>
using namespace std;
int main() {
Node<char> A = Node<char>(0, 'A');
Node<char> B = Node<char>(1, 'B');
Node<char> C = Node<char>(2, 'C');
Node<char> D = Node<char>(3, 'D');
minHeap<char> myHeap = minHeap<char>();
//Below doesn't work, something about subscript is not of integrap type
//myHeap.push(A.index, A.value);
//myHeap.push(B.index, B.value);
//myHeap.push(C.index, C.value);
//myHeap.push(D.index, D.value);
cout << A.index << endl;
myHeap.~minHeap();
return 0;
}
Here is Node.h:
#pragma once
template<typename T>
class Node
{
public:
float index;
T value;
Node(float indx, T val);
~Node();
};
template<typename T>
inline Node<T>::Node(float indx, T val)
{
index = indx;
value = val;
}
template<typename T>
inline Node<T>::~Node()
{
}
And finally, minHeap:
#pragma once
template<typename T>
class minHeap
{
private:
T* arr[100];
int arrSize = 0;
void heapifyUp(int indx);
void heapifyDown(int indx);
int getParent(int indx);
int childLeft(int indx);
int childRight(int indx);
int swap(int indxA, int indxB);
public:
minHeap();
~minHeap();
void push(int indx, T val);
void pop();
};
template<typename T>
inline minHeap<T>::minHeap()
{
}
template<typename T>
inline minHeap<T>::~minHeap()
{
delete[] arr;
}
template<typename T>
inline void minHeap<T>::heapifyUp(int indx)
{
if (indx <= 0) return;
int j = getParent(indx);
if (arr[indx] < arr[j]) {
int temp = arr[indx];
arr[indx] = arr[j];
arr[j] = temp;
}
heapifyUp(j);
}
template<typename T>
inline void minHeap<T>::heapifyDown(int indx)
{
int j;
//if no left child
if (childLeft(indx) > arrSize - 1) return;
//if no right child
if (childRight(indx) > arrSize - 1) j = childLeft(indx);
//No children
else j = (arr[childLeft(indx)] < arr[childRight(indx)]) ? (childLeft(indx)):(childRight(indx));
if (arr[indx] > arr[indx]) {
int temp = arr[indx];
arr[indx] = arr[j];
arr[j] = temp;
}
heapifyDown(j);
}
template<typename T>
inline int minHeap<T>::getParent(int indx)
{
return (indx - 1) / 2;
}
template<typename T>
inline int minHeap<T>::childLeft(int indx)
{
return 2 * i + 1;
}
template<typename T>
inline int minHeap<T>::childRight(int indx)
{
return 2 * i + 2;
}
template<typename T>
inline int minHeap<T>::swap(int indxA, int indxB)
{
int tempA = arr[indxA];
int tempB = arr[indxB];
arr[indxA] = tempB;
arr[indxB] = tempA;
return 0;
}
template<typename T>
inline void minHeap<T>::push(int indx, T val)
{
//Something with Array is broken. Fix it pupper
int tempVal = arr[indx];
arr[indx] = val;
arrSize += 1;
heapifyUp(arrSize - 1);
}
template<typename T>
inline void minHeap<T>::pop()
{
int temp = arr[0];
arr[0] = arr[arrSize - 1];
arr[arrSize - 1] = nullptr;
arrSize -= 1;
heapifyDown(0);
}
Why are you calling myHeap.~minHeap();? This results in myHeap being destroyed twice, with the second call trying to free memory that has already been freed. This can cause the error you're seeing.
You can construct your variables a lot more concisely:
Node<char> A(0, 'A');
minHeap<char> myHeap;
I have implemented a List (different from standard c++ list), this is for exercise.
The problema is that after resizing the list, I get segmentation fault.
I have marked the linke when I get seg. fault, I don't know the reason.
The purpose of resize method is to resize the list: let's say that I have a list of 2 integers, if I resize it to 5 I'll get other 3 elements, all initialized to zero.
If instead I have a list of 4 elements, and I resize it to 2, 2 elelements will be cut.
If I have a int list l, l[0] is the first object of the list, l[1] the second...
So I crash when i attempt to resize the list, exactly in the line that I have marked.
#include <iostream>
#include <cassert>
using namespace std;
template<class T>
class List
{
public:
List<T>();
~List<T>();
protected:
List<T> (T info);
public:
int size();
void resize(int length);
void add(T info,int i);
void push(T info);
T pop();
void remove(int i);
T extract(int i);
T get(int i);
friend ostream& operator<< (ostream& out, List<T>& l)
{
List<T>* ptr=l.next;
if(l.info==NULL)
{
while(ptr!=&l)
{
out << *(ptr->info) << "\t";
ptr=ptr->next;
}
}
else
{
out<< *(l.info) <<"\t";
}
return out;
}
friend istream& operator>> (istream& in,List<T>& l)
{
in >> (*l.info);
return in;
}
bool operator== (List<T>& r)
{
bool result=true;
List<T>* p1,*p2;
p1=this;
p2=&r;
assert((p1->info==NULL && p2->info==NULL)||(p1->info!=NULL && p2->info!=NULL));
if(p1->info==NULL)
{
p1=p1->next;
p2=p2->next;
result=(p1->length == p2->length);
while(result && p1!=this)
{
result=(*(p1->info)==*(p2->info));
p1=p1->next;
p2=p2->next;
}
}
else
{
result=(*(p1->info)==*(p2->info));
}
return result;
}
List<T>& operator+= (List<T>& l)
{
List<T>* ptr;
ptr=l.next;
while(ptr!=&l)
{
this->push(*(ptr->info));
ptr=ptr->next;
}
return *this;
}
List<T>& operator[] (int i)
{
List<T>* ptr;
ptr=this;
assert(i<length);
for(int j=0;j<=i;j++)
ptr=ptr->next;
return *ptr;
}
private:
T *info;
List <T>* next;
List <T>* prev;
int length;
};
template <class T>
List<T>::List ()
{
info=NULL;
next=this;
prev=this;
length=0;
}
template<class T>
List<T>::List (T info)
{
next=this;
prev=this;
this->info=new T();
*(this->info)=info;
}
template<class T>
List<T>::~List()
{
List<T>* ptr, * temp;
ptr=this->next;
if(this->info==NULL)
{
while(ptr!=this)
{
delete ptr->info;
temp=ptr;
ptr=ptr->next;
delete temp;
}
}
}
template<class T>
int List<T>::size()
{
return length;
}
template<class T>
void List<T>::resize(int length)
{
assert(length>=0);
if(this->length<length)
{
for(int i=this->length;i<length;i++)
push(0);
}
else
{
for(int i=length;i<this->length;i++)
extract(this->length-1); // here I call exctract, extract calls
} // remove, remove calls get
}
template<class T>
void List<T>::add(T info,int i)
{
List<T>* ptr,*t1,*t2;
length++;
ptr=&((*this)[i]);
t1=ptr->prev;
t2=ptr;
ptr=new List<T>(info);
t1->next=ptr;
ptr->prev=t1;
t2->prev=ptr;
ptr->next=t2;
}
template<class T>
void List<T>::push(T info)
{
add(info,length-1);
}
template<class T>
void List<T>::remove(int i)
{
List<T>* ptr,*t1,*t2;
ptr=&((*this)[i]);
t1=ptr->prev;
t2=ptr->next;
delete ptr;
t1->next=t2;
t2->prev=t1;
length--;
}
template<class T>
T List<T>::extract(int i)
{
T temp=this->get(i);
remove(i);
return temp;
}
template<class T>
T List<T>::get(int i)
{
assert(i<length);
return *(this[i].info); // here i have seg. fault !!!!!!!!!!
} // I cannot figure why ...
template<class T>
T List<T>::pop()
{
return extract(length-1);
}
int main(int argc, char **argv)
{
List<int> l;
l.resize(3);
for(int i=0;i<3;i++)
cin>>l[i];
l.resize(2);
cout<<l<<endl;
return 0;
}
I hope it's not a too kilometric doce, thanks in advance for who will read and try to help me.
In resize, the for loops change i and compare it with this->length, but both push and extract change this->length, so you're comparing two changing variables against each other.
This may be better a better approach:
while(this->length < length)
push(0);
I want to take this merge_sort I wrote and put it into a class. Because their is some coupling of the variables, particularly - left, right_begin, right...I want to make these class members. The variables that are local to each function I will leave as local function variables.
Also this function will be used for another class I have called dynamic_array which is a bit more efficient than vector. However I want to make it available to the STL vector as well.
How do I do this. Do I use inheritance? Do I make the class a composite class of my dynamic_array...If I do this it will not be available to vector though.
The Question:
How do I make my merge_sort class interface with the STL container Vector and to my own container dynamic_array.
This is for an interview preparation.
Thank you. Dynamic Array code below(remove old merge_sort cold)
Merge Sort Code - to be converted to a class
#include <iostream>
using namespace std;
const int size=8;
int scratch[size],array[size]={6,5,3,1,8,7,2,4};
void print_array(int arr[]){ for (int i = 0; i < size; i++) cout << arr[i] << endl;}
void flip_if_unordered(int &x, int &y)
{
if(array[x]>array[y])
{
int tmp = array[x];
array[x] = array[y];
array[y] = tmp;
}
}
void merge_algo(int &left, int &right_begin, int &right)
{
int iter,iter_left=left,iter_right=right_begin;
for(iter=left;iter<=right;++iter)
{
if( (iter_right>right) || ((iter_left < right_begin) && (array[iter_left]<=array[iter_right])))
{
scratch[iter]=array[iter_left];
++iter_left;
}
else
{
scratch[iter]=array[iter_right];
++iter_right;
}
}
for(iter=left;iter<=right;++iter){array[iter]=scratch[iter];}
}
void merge_recurse(int left,int right)
{
int left_end=(left+((right-left)/2));
int right_begin=left_end+1;
if(((left+1)==right)){flip_if_unordered(left,right);return;}
else if ((left==right)){return;}
else
{
merge_recurse(left,left_end);
merge_recurse(right_begin,right);
merge_algo(left,right_begin,right);
}
}
int main()
{
merge_recurse(0,(size-1));
print_array(array);
return 0;
}
Dynamic Array
#include "c_arclib.cpp"
using namespace std;
template <class T> class dynamic_array
{
private:
T* array;
T* scratch;
void merge_recurse(int left, int right)
{
if(right == left + 1)
{
return;
}
else
{
int i = 0;
int length = right-left;
int midpoint_distance = length/2;
int l = left, r = left + midpoint_distance;
merge_recurse(left, left + midpoint_distance);
merge_recurse(left + midpoint_distance, right);
for(i = 0; i < length; i++)
{
if((l < (left + midpoint_distance)) && (r == right || array[l] > array[r]))
{
scratch[i] = array[l];
l++;
}
else
{
scratch[i] = array[r];
r++;
}
}
for(i = left; i < right; i++)
{
array[i] = scratch[i - left];
}
}
}
void quick_recurse(int left, int right)
{
int l = left, r = right, tmp;
int pivot = array[(left + right) / 2];
while (l <= r)
{
while (array[l] < pivot)l++;
while (array[r] > pivot)r--;
if (l <= r)
{
tmp = array[l];
array[l] = array[r];
array[r] = tmp;
l++;
r--;
}
}
if (left < r)quick_recurse(left, r);
if (l < right)quick_recurse(l, right);
}
public:
int size;
void rorder();
void order();
void randorder();
dynamic_array(int sizein)
{
size=sizein;
array=new T[size]();
}
void print_operator(std::ostream &os = cout) const
{
for (int i = 0; i < size; i++) os << array[i] << endl;
}
int merge_sort()
{
scratch = new T[size]();
if(scratch != NULL)
{
merge_recurse(0, size);return 1;
}
else{return 0;}
}
void quick_sort()
{
quick_recurse(0,size);
}
};
template <class T> void dynamic_array<T>::randorder()
{
srand(time(NULL));
int *ap;
for(ap=array;ap!=array+size;++ap){*ap=rand();}
}
template <class T> void dynamic_array<T>::order()
{
int *ap,i=0;
for(ap=array;ap!=array+size;++ap)
{
*ap=i;
++i;
}
}
template <class T> void dynamic_array<T>::rorder()
{
int *ap,i=size;
for(ap=array;ap!=array+size;++ap)
{
*ap=i;
--i;
}
}
template<class T> ostream& operator<<(ostream& stream, dynamic_array<T> const& data)
{
data.print_operator(stream);
return stream;
}
int main()
{
dynamic_array<int> d1(10);
d1.order();
cout << d1;
/*
clock_t time_start=clock();
d1.merge_sort();
clock_t time_end=clock();
double result = (double)(time_end - time_start) / CLOCKS_PER_SEC;
cout << result;
cout << d1;
*/
}
Just make it a template. You need 2 template parameter, the type of the elements, and the type of the container.
Tipp: if you want to use the class "like a function" define the operator ()
template<class _Item, class _Container> MergeSort
{
...
operator () (_Container & C);
...
}
now you can use C[] and to access elemets for any class that defines operator [], and you can use the size() function with any class that has it. You only have to add them to your dynamic_array class, and you can use MergeSort<int, vector<int> > with vectors, and MergeSort<int, dynamic_array<int> > with dynamic arrays.
Can someone tell me if this is correct. I'm trying to overload my << operator for an array in my dynamic array class below.
Specefically,
Can I put std:ostream in the class itself? This does not seem corrrect. Compiler error is telling me it should only take one argument.
void print_array(std::ostream &os = cout)
{
for (int i = 0; i < size; i++) os << array[i] << endl;
}
std::ostream& operator<<(std::ostream& stream, dynamic_array const& data)
{
data.print_array(stream);
return stream;
}
Dynamic Array Class
/*
Needs a reszie function added
Merge sort is better for sequential, stable(equal elements not re-arranged, or
*/
#include "c_arclib.cpp"
template <class T> class dynamic_array
{
private:
T* array;
T* scratch;
void merge_recurse(int left, int right)
{
if(right == left + 1)
{
return;
}
else
{
int i = 0;
int length = right - left;
int midpoint_distance = length/2;
int l = left, r = left + midpoint_distance;
merge_recurse(left, left + midpoint_distance);
merge_recurse(left + midpoint_distance, right);
for(i = 0; i < length; i++)
{
if((l < (left + midpoint_distance)) && (r == right || array[l] > array[r]))
{
scratch[i] = array[l];
l++;
}
else
{
scratch[i] = array[r];
r++;
}
}
for(i = left; i < right; i++)
{
array[i] = scratch[i - left];
}
}
}
void quick_recurse(int left, int right)
{
int l = left, r = right, tmp;
int pivot = array[(left + right) / 2];
while (l <= r)
{
while (array[l] < pivot)l++;
while (array[r] > pivot)r--;
if (l <= r)
{
tmp = array[l];
array[l] = array[r];
array[r] = tmp;
l++;
r--;
}
}
if (left < r)quick_recurse(left, r);
if (l < right)quick_recurse(l, right);
}
public:
int size;
dynamic_array(int sizein)
{
size=sizein;
array = new T[size]();
}
void print_array(std::ostream &os = cout)
{
for (int i = 0; i < size; i++) os << array[i] << endl;
}
std::ostream& operator<<(std::ostream& stream, dynamic_array const& data)
{
data.print_array(stream);
return stream;
}
void print_array()
{
for (int i = 0; i < size; i++) cout << array[i] << endl;
}
int merge_sort()
{
scratch = new T[size]();
if(scratch != NULL)
{
merge_recurse(0, size);
return 1;
}
else
{
return 0;
}
}
void quick_sort()
{
quick_recurse(0,size);
}
void rand_to_array()
{
srand(time(NULL));
int* k;
for (k = array; k != array + size; ++k)
{
*k=rand();
}
}
void order_to_array()
{
int* k;
int i = 0;
for (k = array; k != array + size; ++k)
{
*k=i;
++i;
}
}
void rorder_to_array()
{
int* k;
int i = size;
for (k = array; k != array + size; ++k)
{
*k=i;
--i;
}
}
};
int main()
{
dynamic_array<int> d1(1000000);
d1.order_to_array();
clock_t time_start=clock();
d1.merge_sort();
clock_t time_end=clock();
double result = (double)(time_end - time_start) / CLOCKS_PER_SEC;
cout << result;
}
Put the operator outside of your class:
template <class T> class dynamic_array
{
...
// if you need to use protected/private members:
friend std::ostream& operator<<(std::ostream& stream,
dynamic_array<T> const& data);
}
template <class T>
std::ostream& operator<<(std::ostream& stream, dynamic_array<T> const& data)
{
data.print_array(stream);
return stream;
}
Since the left operand of the operator<< will be the ostream, not the dynamic array object, you need to implement operator<< as a global function, not a member function (a member function overload is always invoked as object.operator<<(argument), so the object of which it's a member must be the left operand.
If that needs access to the internals of the object, you can make it a friend. If (as in this case) it uses only the public interface of the object (print_array, in your case), then it can just be a normal global function.
template <class T>
class dynamic_array {
// ...
};
template <class T>
std::ostream &operator<<(std::ostream &os, dynamic_array<T> const &a) {
a.print_array(os);
return os;
}
Personally, however, I'd probably make print_array a private member, and make the global operator<< a friend. This reduces the public interface of the class a bit (i.e., only one way to print a dynamic_array instead of two) with no loss of functionality (since the do precisely the same thing).