I'm playing around with associative arrays right now and I can't
seem to figure out how to add additional objects to the array. I
tried insert but it doesn't recognize both arguments.
Also, if I do this it produces an error:
Node[bool] test;
Node node;
Node[bool] temp = [ false:node ];
test ~= temp;
//Error 1 Error: cannot append type Node[bool] to type
//Node[bool] C:\Users\CP\Documents\Visual Studio
//2010\Projects\D\STDS\NPC.d 256
Does this mean you can't use the append operator on associative
arrays ?
To add a single element, just assign it like you would for any other type of array.
test[false] = node;
To append an assoc array to another assoc array, loop over it, and reassign the elements.
foreach(k, v; temp) test[k] = v;
The why: Associative arrays are not lists; as the name suggests, they are, well, associative arrays. The append operator would make sense for consecutive list of elements. D's AAs are hash tables.
Are you looking for an array of associative arrays? In that case, the following would work, as an example:
struct Node { int x; }
Node[bool][] test;
Node[bool] temp = [ false:Node(1), true:Node(2) ];
test ~= temp;
test ~= [ false:Node(3), true:Node(4) ];
writefln("Nodes: %s", test); // Nodes: [[false:Node(1), true:Node(2)], [false:Node(3), true:Node(4)]]
Which would give you a linear array (test), each element of which is an associative array with a maximum of two elements (since your key type is bool).
However, are you trying to create a binary tree instead? Then you'd want Node member variables inside the Node struct itself for the left and right branches (please disregard if this isn't the case).
Related
How to create dynamic array of structs in c++ with keys that are not continous?
I have a struct like this:
struct Data {
int name;
int val;
}
I'm reading names from file of variable length.
Let's say it is:
1 2
3 5
7 12
In the end I'd like to have an (dynamic) array indexed by name,
like this (pseudo code):
arr[1] = *Data(1,2)
arr[3] = *Data(3,5)
arr[7] = *Data(7,12)
Expected result:
cout << arr[7]->val // outputs 12
cout << arr[3]->val // outputs 5
// array size = 3
How to write this in c++?
(assuming only basic feaures, no vectors, maps etc.)
So far I've tried something like this:
Data *distances = new Data[15]; // explicit size works
// Data *distances = new Data; // this don't
distances[5] = myDataStruct;
This allocates memory for exactly one Data element.
Data *distances = new Data;
This allocates memory for 15 Data elements.
Data *distances = new Data[15];
To get what you want you could either
allocate a maximum number of elements and always stay in this boundary or
allocate a number of elements and for each new element resize the array (either C style malloc/realloc/free or C++ style new/delete, but then for resizing you need to and allocate a new array and copy the old values) or
provide a class that internally stores a list of all elements and exports an operator[] which does not do an array lookup but a find in the list
Naïve implementation (this doesn't support adding new elements into the array, only lookup from an existing one. I'll leave a complete implementation as an exercise to the reader):
struct associative {
Data* data_arr;
Data* end;
Data* operator[](int i) {
return linear_search(data_arr, end, i);
}
};
You could use std::find (with custom predicate) in place of linear_search but if that isn't included in "basic features" by your definition, then you'll just have to re-implement it. Linear search is not difficult to implement.
Few ways this naïve data structure can be improved:
RAII ownership over the pointed memory would make the data structure much safer to use.
Support for adding new elements into the internal array
A better data-structure instead of an array: Binary search tree, or a hash map would allow asymptotically faster lookup.
You are now re-implementing std::map or the unordered variant. Consider not reinventing the wheel.
Is there any already created structure which would be simply basic array of doubly linked list nodes?
I mean then you use get(int index) it would return element directly from array (array[i].element). With this structure I could easily do foreach too because every element would be linked to each other, so I would not need to think about blank array places.
Q: Why I need this ?
A: I have unlimited memory, I know how big array I need and I want that structure would be fastest.
Here is a small C++11 container guide, just set your constraints and follow the arrows:
IMO std::deque is the most probable candidate.
In case you want to create something yourself, here is an example of how could it look like:
struct Node{
// constructor
Node (int v, Node* n = 0, Node* p = 0)
: value(v), next(n), prev(p) { }
// data member
int value;
// pointer to next node
Node* next;
// pointer to previous node
Node* prev;
};
size_t number_of_nodes = 10;
Node* ptr = new Node[number_of_nodes];
Based on your description, I think the most fitting data structure would be a double-ended queue; or, in C++, a std::deque.
How it's like a doubly-linked list:
Stores back and front pointers
{push,pop}_{front,back} are O(1)
Doesn't need reallocs when expansion is necessary
How it's like an array:
Allows subscript indexing
O(1) random access
The get operation you're looking for is operator[] or std::deque::at.
Some considerations are that insertion/removal of elements not on polar ends of the structure (i.e., somewhere in the middle) are average case O(n) on the number of elements for the same reason it's O(n) to remove an element from a basic array.
Obligatory basic-use-case
I think what you are looking for is the container deque already present in the STL. See -> http://en.cppreference.com/w/cpp/container/deque
If it is not the one you are looking for, you probably find the container you need here --> http://www.cplusplus.com/reference/stl/
Hope this help
I'm trying to make a remove function for an array class that uses an array of pointers to store objects.
So what I've got is a list of pointers to objects declared like so:
objname* list = new objname[100];
Note, its declared as a member of a class, lets call it myClass.
What I want is to make a function to myClass that takes an index as a parameter, and removes the object from list on that index. Here's what I've got and what I want to do.
void myClass::remove(int index)
{
objname* temp = new objname[listlen]; //creating a temporary list to copy values from the "main" list.
//want to copy elements from 0 to index in "this->list" and store inside temp, then skip one element and copy the rest.
}
There might be a better way to get this functionality and if so I'm open to suggestions.
What I want is to make a function to myClass that takes an index as a parameter, and removes the object from list on that index.
You can do this easily with an std::vector and std::next:
#include <vector> // for std::vector
#include <iterator> // for std::next
std::vector<objname> v;
void myClass::remove(int index)
{
v.erase(std::next(v.begin(), index));
}
Obviously you should first check that the vector is large enough for index.
But if what you really want to do is copy a portion of one array into another, again, you can easily do this with standard library components:
std::vector<objname> v = ...;
std::vector<objname> temp(v.begin(), std::next(v.begin(), index));
Here, temp will contain copies of the first index elements of v.
If you use arrays and are not yet allowed to use std::vector then you can do the task by applying two times standard algorithm std::copy
For example, (I suppose that listlen is the size of the original array)
#include <algorithm>
//...
objname* temp = new objname[listlen - 1];
std::copy( std::next( list + index ), list + listlen,
std::copy( list, list + index, temp ) );
Expression std::next( list + index ) can be substituted for list + index + 1 provided that for the both expressions index is less than listlen.
If I manually type this script and call the calculator :
integer array[100];
Then my calculator will create a vector<int> object with the name "array" contains 100 elements.
But C++ code is unique. For example if I type and call :
integer array[100][100];
integer array[100][100][100];
//etc
Then the template vector<int> is illegal.... :(
So annoying! I tried but I could not find the better solution. Could anyone give me some hint?
This answer covers to generally different approaches.
To support arbitrarily nested, dynamically sized arrays (so the depth of the nested arrays is not limited during compile time), you should use something like the following.
The type of a variable in your scripting language should be either:
integer
float
(... other primitive types you want to support ...)
an array of any of these types (including array)
(... other container types such as an associative map if you want to support it ...)
This is typically done using a "variant" type, such as Boost Variant or QVariant in Qt. A variant type is basically a union of a set of types (so it is one of them) plus a type descriptor which tells which type it actually contains.
So an array of any type can be represented, also if this "any type" is an array again. So you can support a dynamic depth of nested arrays.
Note that the "array of any types" should actually be a vector of this variant type. The problem with Boost Variant is that you have to explicitly list the types it can hold as template arguments. This will result in a recursion:
boost::variant<int, float, ..., std::vector<boost::variant<..., ...> > >
^^^^^^^^^^^^^^^^^^^^^^^^
recursion
In Qt there is the type QVariant which can hold basically any type supported by Qt. QVariant is not a template class and thus its type doesn't contain such a recursion. I don't know if there is a comparable boost type, but I doubt it.
If your arrays can't be resized during execution of the script (or if they should be resized, you can allocate a new one and copy the contents), there is a simpler solution. Just store the arrays in a one-dimensional vector, also store the dimensions of the array in your scripting language in another vector. Then you can use an index method like the following.
class ScriptArray {
vector<int> dim;
vector<int> elements;
int getIndex(vector<int> indexList) const {
int multiplicator = 1;
int index = 0;
for (int i = 0; i < dim.size(); ++i) {
index = multiplicator * indexList[i];
multiplicator *= dim[i];
}
return index;
}
};
This is basically a generalization of the following idea. Consider a two-dimensional array (100 x 100 elements) you want to represent as a one-dimensional one (10000 elements). For any index in the original array (x, y) you can map this to a one-dimensional index for your internal array (x + 100 * y). For a three-dimensional array this just contains another multiplication (x + 100 * y + 100*100 * z) and so on...
The problem with this solution and resizing the array is that the elements "move" within the array when the size of a dimension changes (special case: last dimension, as this dimension is the "outermost" one). So either you can live with the fact that the array would be invalid when resized, or you copy the contents in a new array with the new size, or you implement some complicated resize method which carefully inserts spaces / removes some elements in the array at the correct places.
I am assuming that you have created your own language that you want to parse using C++. Your parser knows that you are defining a variable, since it finds the type integer before an identifier. What you then have to do is check if you have to create a normal variable or a multi-dimensional array.
If no brackets ([]) exist -> Normal variable
If brackets exist -> Make a loop to count how many there are. Then allocate nested
vectors. Only the final vector will have elements of type int.
So the easiest way to implement this is to forget about an array and just view it as a special case of a multi-dimensional array with only one bracket.
what's the difference between those pieces of code?
1)
struct MyStruct
{
int num;
} ms[2];
ms[0].num = 5;
ms[1].num = 15;
2)
struct MyStruct
{
int num;
MyStruct *next;
};
MyStruct *ms = new MyStruct;
ms->num = 5;
ms->next = new MyStruct;
ms->next->num = 15;
I'm probably a little confused about linked-lists and lists in general, are they useful to something in particular? Please explain me more.
Your first definition...
struct MyStruct
{
int num;
} ms[1];
...creates a statically allocated array with a single element. You cannot change the size of the array while your program is running; this array will never hold more than one element. You can access items in the array by direct indexing; e.g., ms[5] would get you the sixth element in the array (remember, C and C++ arrays are 0-indexed, so the first element is ms[0]), assuming that you had defined an array of the appropriate size.
Your second definition...
struct MyStruct
{
int num;
MyStruct *next;
};
...creates a dynamically allocated linked list. Memory for this list is allocated dynamically during runtime, and the linked list can grow (or shrink) during the lifetime of the program. Unlike arrays, you cannot directly access any element in the list; to get to the sixth element you have to start at the first element and then iterate 5 times.
Regarding errors you have in your code, the first one constructs a static number of MyStruct elements and store them in ms array, so ms is an array of MyStruct structures, of course in this you meant it to be of 2 elements only, later on you can't add any other element to ms array and though you have limited the number of MyStruct elements, while in the second case when you have a linked list you can chain as many MyStruct elements as you want and this will lead to dynamic number of MyStruct elements, the second case let you add as many MyStruct as you want during the run time, the second case should look like this conceptually in memory:
[ MyStruct#1 ] ----> [ MyStruct#2 ] ----> [ NULL ]
NULL though could be a MyStruct#3 for example, while the first one:
[ MyStruct#1 ] ----> [ MyStruct#2 ]
and that's it, no MyStruct#3 can be added.
Now let's go through the code you wrote:
struct MyStruct
{
int num;
} ms[1];
ms[1] really means create me an ms array of one MyStruct element.
The code next assume you created two:
ms[0].num = 5;
ms[1].num = 15
Hence it should have been:
struct MyStruct
{
int num;
} ms[2];
And it will work fine! and keep in mind the simple illustration I made for it:
[ MyStruct#1 ] ----> [ MyStruct#2 ]
Second Case:
struct MyStruct
{
int num;
MyStruct *next;
};
MyStruct *ms = new MyStruct;
ms->num = 5;
ms->next = new MyStruct;
ms->next->num = 15;
This code uses the C++ operator new if you save your source code as .cpp you'll be able to compile as C++ application with no errors, while for C, the syntax should change like so:
struct MyStruct
{
int num;
MyStruct *next;
};
MyStruct *ms = (MyStruct *) malloc(sizeof MyStruct);
ms->num = 5;
ms->next = (MyStruct *) malloc(sizeof MyStruct);
ms->next->num = 15;
and don't forget to include #include <stdlib.h> for the malloc() function, you can read more about this function here.
And as the first case recall my illustration for the linked-list:
[ MyStruct#1 ] ----> [ MyStruct#2 ] ----> [ NULL ]
Where NULL is actually the next element of the ms->next MyStruct structure, to explain it more recall that ms->next is a pointer of MyStruct and we have allocated it a space in the heap so now it's pointing to a block of memory of the same size of MyStruct structure.
Finally here is a Stackoverflow question about when to use a linked-list and when to use an array so you can get exactly why people all around the world prefer linked-list sometimes and array other times.
Oh, my friend, there are dozens of different kinds of data structures that pretty much just hold a bunch of num values or whatever. The reason programmers don't just use arrays for everything is the differences in the amount of memory required, and the ease of doing whichever operations are most important for your particular needs.
Linked lists happen to be very quick at adding or removing individual items. The trade off is that finding an item in the middle of the list is relatively slow, and the extra memory required by the next pointers. A properly-sized array is very compact in memory, and you can access an item in the middle very quickly, but to add a new item at the end you either have to know the maximum number of elements beforehand, which is often impossible or wastes memory, or reallocate a larger array and copy everything over, which is slow.
Therefore, someone who doesn't know how big their list needs to be, and who mostly only needs to deal with items at the beginning or end of the list or always loops over the entire list, and cares more about execution speed than saving a few bytes of memory, is very likely to choose a linked list over an array.
The main differences between lists and arrays in general:
Ordering in lists is explicit; each element stores the location of the preceding/succeeding element. Ordering in arrays is implicit; each element is assumed to have a preceding/succeeding element. Note that a single list may contain multiple orderings. For example, you could have something likestruct dualList {
T data1;
K data2;
struct dualList *nextT;
struct dualList *nextK;
};
that allows you to order the same list two different ways, one by data1 and the other by data2.
Adjacent array elements are in adjacent memory locations; adjacent list elements don't have to be in adjacent locations.
Arrays offer random access to their elements; lists only offer sequential access (i.e., you have to walk down the list to find an element).
Arrays are (usually) fixed in length1 - adding elements to or removing elements from the array doesn't change the array's size. Lists can grow or shrink as needed.
Lists are great for maintaining a dynamically changing sequence of values, especially if the values need to remain ordered. They're not so hot for storing relatively static data that needs to be retrieved quickly and frequently, since you can't access elements randomly.
You can get around this by declaring memory dynamically, and then use realloc to resize that memory block as needed, but it needs to be done carefully and can be a bit of a PITA.
Linked lists are useful when element ordering is important, and the number of elements is not known in advance. Besides, accessing an element in linked list takes O(n) time. When you look for an element in a list, in the worst case, you'll have to look at every element of a list.
For array, the number must be known in advance. When you define an array in C, you have to pass it its size. On the other hand, accessing an array element takes O(1) time, since an element can be addressed by index. With linked list, that is not possible.
However, that is not C++ related question, since the concept of linked list and array is not tied to C++.
An array is a contiguous pre-allocated block of memory whereas a linked list is a collection of runtime allocated ( malloc ) pieces of memory ( not necessarily contiguous ) linked to each other via pointers ( *next ). You would generally use an array of structs if you know at compile time the maximum number of elements you need to store. A linked list of structs however is useful if you don't know the maximum number of elements that will need to be stored. Also with a linked list the number of elements may change, add and remove elements.