質問

I need a data structure in which each element has a specific index but can also be retrieved using a key.

I need that data structure for model-view Programming in Qt. On the one hand, the View asks for an element in a specific row. On the other hand, the model wants to insert and modify elements with a given key. Both operations should run in O(1).

Here is an example of what I want:

The View sees the following:

list[0]: "Alice", aged 22
list[1]: "Carol", aged 15
list[2]: "Bob", aged 23

The Model sees:

hash["Alice"]: "Alice", aged 22
hash["Bob"]: "Bob", aged 23
hash["Carol"]: "Carol", aged 15

My idea was the following: I have a QList<Value> and a QHash<Key, Value*>. The hash points to the place in the list, where the corresponding element is stored. This is the code to insert/edit values:

if (hash.contains(key))
    *hash[key] = value;
else
{
    int i = list.size();
    list << value;
    hash[key] = &list[i];
}

The problem is that this code does not always work. Sometimes it works as expected, but it happens that the data structure is not consistent any more.
I suspect, it is because QList moves it's content through memory because it allocates new space or something like that.

Operations which are important (should run in expected O(1)):

  • Insert key/value pair (appends the value to the end of the list)
  • Look up and modify a value using a key
  • Look up and modify a value using an index

Other operations which have to be possible, but don't have to be possible in constant run time:

  • Delete an element by index
  • Delete an element by key
  • Insert in the middle of the array
  • Swap elements in the array / sort array
  • Get the index of a key

My two questions are:

  • Is there any data structure which does what I want?
  • If there is not, how could I fix this or is there a better approach?
役に立ちましたか?

解決

Approach 1: Instead of the pointer, you can store the list index in the hash. Then you have one more indirection (from the hash, you get the index, then you retrieve from the list), but it is still O(1). The difference in speed should not be too much.

Approach 2: Both the list and the hash operate with pointers. Then they will stay valid. However, deleting based on index or key will become O(n), as you have to find the object manually in the non-corresponding container.

I also wonder how you want to solve the issue of deletion by index or insertion in the middle anyway. In both cases, the hash will point to wrong entries (both in your approach and Approach 1). Here you would be forced to go with Approach 2.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top