Constructor for LinkedList to receive an array C++ - c++

Attempting to write a constructor for LinkedList to be initialised with an array of integers.
The program would call linked(array); which will add all the values within the array in to a linkedlist.
LinkedList::LinkedList(int array[])
{
headPtr->setData(array[0]); //setData method stores the integer at position 0 inside headPtr
Node *currentPtr = headPtr;
for (int i = 0; i < array.length(); ++i) //for loop to add the integers to the next node
{
currentPtr->setNext(new Node(array[i])); //creates a new node with the integer value of array position i
}
}
the trouble is the array.length (coming from Java) and I don't think the array length can be obtained this way?

I would suggest you to use iterator idiom, and make the constructor a templated constructor as:
class LinkedList
{
//...
public:
template<typename FwdIterator>
LinkedList(FwdIterator begin, FwdIterator end)
{
for (;begin != end; ++begin)
{
//treat begin as pointer, and *begin as dereferenced object
}
}
//...
};
And then you can use it as:
int arr[] = {1,2,3,4,5,6,7,8,9,10};
LinkedList lnklist(arr, arr+10);
Not only that. If you've std::vector<int>, then you can also use it to construct the linked list, as:
std::vector<int> v;
//..
LinkedList lnklist(v.begin(), v.end());
So using iterator idiom gives you this much power and flexibility. :-)

As Nawaz explained, going with iterator solution is better. But if you want to go with array ( static one though), then compiler can automatically deduce the size for you.
template<size_t size>
LinkedList::LinkedList(int (&array)[size])
{
headPtr->setData(array[0]); //setData method stores the integer at position 0 inside headPtr
Node *currentPtr = headPtr;
for (int i = 0; i < size++i) //for loop to add the integers to the next node
{
currentPtr->setNext(new Node(array[i])); //creates a new node with the integer value of array position i
}
}
Can be called as shown below.
int arr[] = {1,2,3,4,5,6,7,8,9,10};
LinkedList lnklist(arr);

Like others have said, it is not only important but vital that you get a good introductory C++ book and read it from front to back, simultaneously trying to forget what you know about Java while in C++ mode. They are not remotely similar.
Now to your problem, it can be solved by using std::vector and using its size method:
// put this with the other includes for your file
#include <vector>
LinkedList::LinkedList(const std::vector<int>& array)
{
headPtr->setData(array[0]); //setData method stores the integer at position 0 inside headPtr
Node *currentPtr = headPtr;
for (int i = 0; i < array.size(); ++i) //for loop to add the integers to the next node
{
currentPtr->setNext(new Node(array[i])); //creates a new node with the integer value of array position i
}
}
If you don't want to use vector, you have to pass in the size of the array to the function:
LinkedList::LinkedList(int array[], int arrlen)
{
headPtr->setData(array[0]); //setData method stores the integer at position 0 inside headPtr
Node *currentPtr = headPtr;
for (int i = 0; i < arrlen; ++i) //for loop to add the integers to the next node
{
currentPtr->setNext(new Node(array[i])); //creates a new node with the integer value of array position i
}
}
But it is recommended to use the vector version.

Related

Delete Zero in ArrayList in C++

Inside the ArrayList I'm trying to delete all possible 0's that are appended as input, but for now it only deletes just one 0, no matter where it is located. But seems like I can't delete more than one zero at the time. How can I fix this?
void AList::elimZeros(){
int i;
int curr = 0;
for(i=0; i < listSize; i++) {
if ( (listArray[i] != 0 ) && (curr<listSize) ){
listArray[curr] = listArray[i];
curr++;
}
else if (listArray[i] == 0 )
{
listArray[curr] = listArray[i+1];
listSize--;
curr++;
}
}
}
This is the class for the ADT
class AList : public List {
private:
ListItemType* listArray; // Array holding list elements
static const int DEFAULT_SIZE = 10; // Default size
int maxSize; // Maximum size of list
int listSize; // Current # of list items
int curr; // Position of current element
// Duplicates the size of the array pointed to by listArray
// and update the value of maxSize.
void resize();
public:
// Constructors
// Create a new list object with maximum size "size"
AList(int size = DEFAULT_SIZE) : listSize(0), curr(0) {
maxSize = size;
listArray = new ListItemType[size]; // Create listArray
}
~AList(); // destructor to remove array
This is the input I'm testing with:
int main() {
AList L(10);
AList L2(20);
L.append(10);
expect(L.to_string()=="<|10>");
L.append(20);
expect(L.to_string()=="<|10,20>");
L.append(30);
L.append(0);
L.append(40);
L.append(0);
L.append(0);
expect(L.to_string()=="<|10,20,30,0,40>");
L.elimZeros();
expect(L.to_string()=="<|10,20,30,40>");
assertionReport();
}
It'd be helpful if you posted the class code for AList. Think you confused Java's ArrayList type, but assuming you're using vectors you can always just do:
for (int i = 0; i < listSize; i++) {
if(listArray[i] == 0) listArray.erase(i);
}
EDIT: Assuming this is the template of for the AList class, then there is simply a remove() function. In terms of your code, there are two issues.
You reference listSize in the for loop, then decrement it inside of the loop. Each iteration evaluates the value separately so you're reducing the number of total loop iterations and stopping early.
The other thing is if the entry is zero you shouldn't increment curr and set listArray[curr] = listArray[i+1]. This is basically assuming the next entry will not be a zero. So if it is, then you're copying the element and moving to the next. Your if statement can be cleaned up with:
if (listArray[i] == 0) {
listSize--;
} else {
listArray[curr] = listArray[i];
curr++;
}

Trying to find two random nodes and swap them in a doubly linked list

This program is basically just suppose to shuffle a deck of cards. The cards are stored in a doubly linked list, so 52 nodes. I'm getting a read access error in the getNode function, but I'm pretty sure my loop is correct, so I think the error is stemming from somewhere else. Maybe the swap function. My first step is getting pointers to the nodes that I'm trying to swap.
So I made a function, and I'm pretty sure it's right, except I'm wondering if I should be returning *traverseP instead of just traverseP. I don't think so, because I want to return a pointer to the node, not the value inside the node.
template<class T>
typename ReorderableList<T>::Node *ReorderableList<T>::getNode(int i) const
{
int count = 0;
for (Node *traverseP = firstP; traverseP != NULL; traverseP = traverseP->nextP) {
if (count == i)
return traverseP;
count++;
}
return NULL;
}
Next I made a swap function that take two ints, they represent the values I'm passing into the getNode function
template<class T>
void ReorderableList<T>::swap(int i, int j)
{
// Get pointers to ith and jth nodes.
Node *iPtr = getNode(i);
Node *jPtr = getNode(j);
//create temp Node and store the pointers
Node *temp = new Node;
temp = iPtr->prevP;
temp = iPtr->nextP;
//adjust the iPtr next/prev pointers
iPtr->prevP = jPtr->prevP;
iPtr->nextP = jPtr->nextP;
//adjust the jPtr next/prev pointers
jPtr->prevP = temp->prevP;
jPtr->nextP = temp->prevP;
//I'm a little unclear on these lines. I think they're checking if
//iPtr and jPtr have null pointers. I've tried making them equal jPtr and
//iPtr and that strangly didn't make any difference.
if (iPtr->prevP)
iPtr->prevP->nextP = jPtr;
if (iPtr->nextP)
iPtr->nextP->prevP = jPtr;
if (jPtr->prevP)
jPtr->prevP->nextP = iPtr;
if (jPtr->nextP)
jPtr->nextP->prevP = iPtr;
delete temp;
}
This is the shuffle function where this whole shabang kicks off
template<class T>
void randomShuffle(ReorderableList<T> &list, int n)
{
int randNum = 0;
for (int i = n-1; i > 0; i--)
{
randNum = (rand() & (i + 1));
if (randNum > i)
std::swap(randNum, i);
list.swap(randNum, i);
}
}
I've checked a couple different resources for the swap function and found two that both claimed they were correct, but they looked different to me.
Resource 1
Resource 2

Linked list within a linked list (2D linked list?)

I have a txt file that contains a matrix of chars(1 or 2 at each position in matrix)
C P O Hr S A
N Hw N L Z R
W T O O Ta A
I O S S E T
Something like this. What I managed to do is to create a linked list and store every element of this matrix in that list (separately).
struct DataNode{
char data[3];
struct DataNode *nextData;
};
void initNode(DataNode *head, char x[3]) {
for(int i=0; i<3; i++)
head->data[i]=x[i];
head->nextData=NULL;
}
void addNode(DataNode *head, char x[3]) {
DataNode *newNode = new DataNode;
for(int i=0; i<3; i++)
newNode->data[i]=x[i];
newNode->nextData=NULL;
DataNode *curr = head;
while(curr) {
if(curr->nextData==NULL) {
curr->nextData = newNode;
return;
}
curr = curr->nextData;
}
}
int main() {
char input[3];
if(in.is_open()) {
in>>input;
initNode(head,input);
for(int i=0; i<3; i++)
dieSide[i]=input[i];
while(in>>input) {
addNode(head,input);
}
in.close();
}
}
So far, this works as it should, and I guess I'm happy with it.
What I need now, it another linked list, where the elements would still be char[3] types, but there has to be first a list containing a row of 6 elements, and then, another list, containing all of those 6 element lists.
I hope I made myself clear about my wishes.
I'm thinking about creating another struct, with next pointers to each of two active lists, but still not sure about that idea.
How would you recommend me to go about doing this?
EDIT
Just a little help, please...
I have re-implemented all of the functions to suit the struct you (#Daniel) suggested, and they appear to work. However, I need a way to "reset" the DataNode* I want to use for creating small lists. This way I only get entire matrix printed as many times as there are lines in the file.
What I have is>
char input[3];
int counter=0;
struct DataNode *head = new DataNode; //creates a list of all elements
struct DataNode *head_side = new DataNode; //want to use this one to create smaller lists
struct DieSideNode *head_die = new DieSideNode; //creates a list of smaller lists
if(in.is_open()) {
in>>input;
initNode(head,input);
initNode(head_side, input);
counter++;
while(in>>input) {
addNode(head,input);
addNode(head_side, input);
counter++;
if( counter == 6 ) {
initSide(head_die, head_side);
head_side=0;
}else if(counter%6==0) {
addSide(head_die, head_side);
head_side=0;
}
}
in.close();
}
This code successfully extracts first six elements, and puts it as a first element of the list, but then it stops working there.
I'll give you a little hint to get started. As you know, a linked-list node contains some data and a pointer to the next element of the list. What you call a "2-d linked list" would actually simply be implemented as a linked-list of linked-lists. Each node in the list points to another linked list. So you will need to define a new type:
struct ListNode {
DataNode* dataRowHead;
struct ListNode* nextRow;
};
What you are trying to do would have 6 ListNodes connected as a linked-list. Each ListNode contains a pointer to a DataNode which is the head of a linked-list for the row that corresponds to the ListNode that points to it.
I will leave the implementation up to you.

Array of Linked Lists C++

So I thought I understood how to implement an array of pointers but my compiler says otherwise =(. Any help would be appreciated, I feel like I'm close but am missing something crucial.
1.) I have a struct called node declared:.
struct node {
int num;
node *next;
}
2.) I've declared a pointer to an array of pointers like so:
node **arrayOfPointers;
3.) I've then dynamically created the array of pointers by doing this:
arrayOfPointers = new node*[arraySize];
My understanding is at this point, arrayOfPointers is now pointing to an array of x node type, with x being = to arraySize.
4.) But when I want to access the fifth element in arrayOfPointers to check if its next pointer is null, I'm getting a segmentation fault error. Using this:
if (arrayOfPointers[5]->next == NULL)
{
cout << "I'm null" << endl;
}
Does anyone know why this is happening? I was able to assign a value to num by doing: arrayOfPointers[5]->num = 77;
But I'm confused as to why checking the pointer in the struct is causing an error. Also, while we're at it, what would be the proper protoype for passing in arrayOfPointers into a function? Is it still (node **arrayOfPointers) or is it some other thing like (node * &arrayOfPointers)?
Thanks in advance for any tips or pointers (haha) you may have!
Full code (Updated):
/*
* Functions related to separate chain hashing
*/
struct chainNode
{
int value;
chainNode *next;
};
chainNode* CreateNewChainNode (int keyValue)
{
chainNode *newNode;
newNode = new (nothrow) chainNode;
newNode->value = keyValue;
newNode->next = NULL;
return newNode;
}
void InitDynamicArrayList (int tableSize, chainNode **chainListArray)
{
// create dynamic array of pointers
chainListArray = new (nothrow) chainNode*[tableSize];
// allocate each pointer in array
for (int i=0; i < tableSize; i++)
{
chainListArray[i]= CreateNewChainNode(0);
}
return;
}
bool SeparateChainInsert (int keyValue, int hashAddress, chainNode **chainListArray)
{
bool isInserted = false;
chainNode *newNode;
newNode = CreateNewChainNode(keyValue); // create new node
// if memory allocation did not fail, insert new node into hash table
if (newNode != NULL)
{
//if array cell at hash address is empty
if (chainListArray[hashAddress]->next == NULL)
{
// insert new node to front of list, keeping next pointer still set to NULL
chainListArray[hashAddress]->next = newNode;
}
else //else cell is pointing to a list of nodes already
{
// new node's next pointer will point to former front of linked list
newNode->next = chainListArray[hashAddress]->next;
// insert new node to front of list
chainListArray[hashAddress]->next = newNode;
}
isInserted = true;
cout << keyValue << " inserted into chainListArray at index " << hashAddress << endl;
}
return isInserted;
}
/*
* Functions to fill array with random numbers for hashing
*/
void FillNumArray (int randomArray[])
{
int i = 0; // counter for for loop
int randomNum = 0; // randomly generated number
for (i = 0; i < ARRAY_SIZE; i++) // do this for entire array
{
randomNum = GenerateRandomNum(); // get a random number
while(!IsUniqueNum(randomNum, randomArray)) // loops until random number is unique
{
randomNum = GenerateRandomNum();
}
randomArray[i] = randomNum; // insert random number into array
}
return;
}
int GenerateRandomNum ()
{
int num = 0; // randomly generated number
// generate random number between start and end ranges
num = (rand() % END_RANGE) + START_RANGE;
return num;
}
bool IsUniqueNum (int num, int randomArray[])
{
bool isUnique = true; // indicates if number is unique and NOT in array
int index = 0; // array index
//loop until end of array or a zero is found
//(since array elements were initialized to zero)
while ((index < ARRAY_SIZE) && (!randomArray[index] == 0))
{
// if a value in the array matches the num passed in, num is not unique
if (randomArray[index] == num)
{
isUnique = false;
}
index++; // increment index counter
} // end while
return isUnique;
}
/*
*main
*/
int main (int argc, char* argv[])
{
int randomNums[ARRAY_SIZE] = {0}; // initialize array elements to 0
int hashTableSize = 0; // size of hash table to use
chainNode **chainListArray;
bool chainEntry = true; //testing chain hashing
//initialize random seed
srand((unsigned)time(NULL));
FillNumArray(randomNums); // fill randomNums array with random numbers
//test print array
for(int i = 0; i < ARRAY_SIZE; i++)
{
cout << randomNums[i] << endl;
}
//test chain hashing insert
hashTableSize = 19;
int hashAddress = 0;
InitDynamicArrayList(hashTableSize, chainListArray);
//try to hash into hash table
for (int i = 0; i < ARRAY_SIZE; i++)
{
hashAddress = randomNums[i] % hashTableSize;
chainEntry = SeparateChainInsert(randomNums[i], hashAddress, chainListArray);
}
system("pause");
return 0;
}
arrayOfPointers = new node*[arraySize];
That returns a bunch of unallocated pointers. Your top level array is fine, but its elements are still uninitialized pointers, so when you do this:
->next
You invoke undefined behavior. You're dereferencing an uninitialized pointer.
You allocated the array properly, now you need to allocate each pointer, i.e.,
for(int i = 0; i < arraySize; ++i) {
arrayOfPointers[i] = new node;
}
As an aside, I realize that you're learning, but you should realize that you're essentially writing C here. In C++ you have a myriad of wonderful data structures that will handle memory allocation (and, more importantly, deallocation) for you.
Your code is good, but it's about how you declared your InitDynamicArrayList. One way is to use ***chainListArray, or the more C++-like syntax to use references like this:
void InitDynamicArrayList (int tableSize, chainNode **&chainListArray)

Dynamic tree in C++

I'd like to make a tree which can have some childrens in every node, but i don't know number of them. Tree have to be coded in small memory using (no extra data) with constant time to every node. I tought that i will make class Tree with value and children property (value is int, and children is stack) and array of pointers to every node in that Tree. My problem is to make this array. How can i make it with no extra data (std::vector sometimes allocate more memory than it needs) and constant time to every cell?
Everything's ok, but i also need constant time to every node. I know how many nodes will be, but i dont know how to make array of every node. It should work something like:
array[n];
A_Node *array[0]= new A_Node(16);
A_Node *n = new A_Node(1);
array[0]->addChild(n);
array[1]=n;
Or:
*(array+1)=n;
This is a possible example. It is not a full example solution but I hope you get the point. The point is that you can have a double pointer to nodes, which is basically an array of pointers to nodes of the tree.
Then you can reallocate the size yourself and to however much you want whenever there is a need to. But std::vector already does that for you so there is no real reason not to use it unless you want to control everything yourself or experiment, or are writing something in C. In any case hope this helps.
#include <stdio.h>
#include <stdlib.h>
// The initial buffer length of a node's children
#define BUFFER_LENGTH 5
// How much to multiply with if an addition of a child goes over the buffer
#define MULTIPLIER 2
///Your node class
class A_Node
{
public:
A_Node(int value,unsigned int childrenN=0)
{
this->value = value;
this->childrenN = childrenN;
//allocate BUFFER_LENGTH children for the node at first or childrenN if the childrenN is not initially 0
if(childrenN != 0)
{
this->children = (A_Node**) malloc(sizeof(A_Node*)*childrenN);
this->bufferLength = childrenN;
}
else
{
this->children = (A_Node**) malloc(sizeof(A_Node*)*BUFFER_LENGTH);
this->bufferLength =BUFFER_LENGTH;
}
}
//in the destructor of a node it would need some special care
~A_Node()
{
//for every child call the destructor of each child
for(int i = 0; i < this->childrenN; i++)
{
delete this->children[i];
}
//and only then free the buffer of the pointers to the children
free(this->children);
}
//adds a child
void addChild(A_Node* child)
{
//reallocate if needed
if(childrenN >= this->bufferLength)
{
realloc(this->children,sizeof(A_Node*)*MULTIPLIER);
}
this->children[childrenN] = child;
this->childrenN++;
}
A_Node* getChild(unsigned int i)
{
if(i >= this->childrenN)
{
return 0;
}
return this->children[i];
}
void printValue()
{
printf("%d\n",this->value);
}
private:
int value;
unsigned int childrenN;
A_Node** children;
unsigned int bufferLength;
};
///Your tree class
class A_Tree
{
public:
//constructor
A_Tree(int rootValue)
{
root = new A_Node(rootValue);
}
//destructor
~A_Tree()
{
//recursively kills all the nodes due to the destructor of node
delete root;
}
//your root node
A_Node* root;
};
int main()
{
A_Tree tree(16);
tree.root->addChild(new A_Node(42));
tree.root->printValue();
(tree.root->getChild(0))->printValue();
return 0;
}
Just keep track of the memory yourself rather than using a vector:
class Node {
public:
// In the constructor, initialize your array of children to NULL
// and the size of your children array to zero
Node() : mChildren(NULL), mSize(0) {}
void AddChild(Node* newChild) {
// allocate space for your new array
Node** newArray = new Node*[mSize + 1];
// copy over nodes from old array to new array
for (int i = 0; i < mSize; i++) {
newArray[i] = mChildren[i];
}
// add in our new child to the end of the array
newArray[mSize++] = newChild;
// if there was an old array (null check) free the memory
if (mChildren) {
delete [] mChildren;
}
// set our children array equal to our new array
mChildren = newArray;
}
Node* AccessChild(size_t index) {
// make sure it's a valid index and then return
assert(index < mSize);
return mChildren[index];
}
private:
Node** mChildren;
int mSize;
};
This will have no extra space for extra nodes, but it will require the size of an int in order to keep track of how many nodes you are storing. I don't see any way you could do it without this or having a constant number of children.
Please note, vectors double in size each time they need to reallocate because this is more efficient. While the solution above will be more efficient memory-wise, it will hurt a lot performance wise because it will require an allocation for every child addition, which is going to take O(N) allocations to add N nodes.
The performance of a vector will be O(log(N)) allocations to add N nodes, but again this solution sounds like it has the memory efficiency you're looking for.