遍历并非所有元素都应具有值的元素
Iterate over elements where not all the elements should have a value
我不知道如何描述这一点。我必须遍历通过指针相互连接的对象,但是第一个元素不应该在其类中存储值,只是指向下一个元素的指针。
我想出了一个小的班级层次结构。如果我这样使用它,我必须将基类强制转换为派生元素。它似乎只适用于肮脏的演员阵容。
有没有更好的解决方案?
下面是示例代码:
#include <iostream>
struct Basenode {
Basenode* next;
};
struct Skipnode : Basenode {
Skipnode(int in_key, int in_value);
int key;
int value;
};
Skipnode::Skipnode(int in_key, int in_value)
: key{ in_key }, value{ in_value }
{
}
int main()
try {
Basenode head; // no key and value
Skipnode first(4, 2); // key and value
Skipnode second(8, 2);
Basenode* p = &head;
head.next = &first; // fine
first.next = &second; // fine
// p = p->next->key; // not accesible because is Basenode not derrived Skipnode
std::cout << static_cast<Skipnode*>(p->next)->key; // fine but diryt cast slicing ?
std::cin.get();
}
catch (std::runtime_error& e) {
std::cerr << e.what() << "n";
std::cin.get();
}
catch (...) {
std::cerr << "unknown error " << "n";
std::cin.get();
}
编辑:有人问到评论为什么我需要这个。我想我举了一个有限的例子。
我需要它来实现船长。它的许多算法要求在第一个元素之前从一个元素开始。头部元素。我可以使其成为一个普通节点并为这些值输入虚拟值,但这似乎不正确。所以现在我从你的建议中想出了这个丑陋的解决方案,从头部元素开始。
下面是一个以复制构造函数为例的代码片段。
class Skiplist {
public:
//...
Skiplist(const Skiplist& other); // copy constructor
//...
private:
struct Skipnode; // forward declaration so Basenode can have Skiplist*
struct Basenode { // Empty node, mainly created to represent head element.
// Is there a way to get a empty head with no key / values without using this ?
Basenode(int in_level);
Basenode(const std::vector<Skipnode*>& in_next);
std::vector <Skipnode*> next;
};
struct Skipnode : Basenode { // derived so with Basenode* we can start the iteration of the node on head
Skipnode(value_type val, int in_level);
Skipnode(value_type val, const std::vector<Skipnode*>& in_next);
value_type value; // first key / second mapped type = value
//key_type key;
//mapped_type value;
};
Basenode head{ 0 }; // element before first element containg pointers to all the first elements of each level
//...
};
Skiplist::Skiplist(const Skiplist& other) // copy constructor
:head{ other.head }, top_level{ other.top_level }, random_engine{ other.random_engine }
// on the first level let the other Skiplist present its elements and make a deep copy of them
// now still the higher levels point to the other node so this is fixed in the second part
// then the next level pointers are installed linked to the elements of the new node
{
if (top_level == 0) return; // no elements are present so dont bother to allocate nodes
{
// installment of lowest level, each element is located here
Skipnode* other_node = other.head.next[0];
Basenode* current_position = &head;
while (other_node != nullptr) {
Skipnode* new_node = new Skipnode{ other_node->value,other_node->next };
current_position->next[0] = new_node;
current_position = current_position->next[0];
other_node = other_node->next[0];
}
current_position->next[0] = nullptr;
}
// installment of the other levels
for (size_type curr = 1; curr < top_level; ++curr) {
Basenode* current_position = &head; // the current position of the level[curr]
Skipnode* next_position = current_position->next[curr]; // next position after curr containing still pointers to the other skiplist
Basenode* lowest_position = &head; // lowest level position used to find the new pointers and attach them "behind" current
while (lowest_position != nullptr && next_position != nullptr) {
if (lowest_position->next[0]->value.first == next_position->value.first) { // check by unique key, address of next pos is still of the other skiplist
current_position->next[curr] = lowest_position->next[0]; // lowest is the valid address of new node
current_position = current_position->next[curr];
next_position = next_position->next[curr]; // go to next element of other node
if (next_position == nullptr) { // case end is reached
current_position->next[curr] = nullptr;
current_position = current_position->next[curr];
}
}
else { // forward position of lowest level until other key == next position key
lowest_position = lowest_position->next[0];
}
}
}
}
有关船长组织方式的基本说明,请参阅此处: https://en.wikipedia.org/wiki/Skip_list
整个代码都在代码审查中: https://codereview.stackexchange.com/questions/197752/non-generic-skip-list-implementation-in-c-version-2
@SomeProgrammerDude所说的所有事情,或者:
我认为根本不需要类BaseNode
。 为什么我们不能只拥有(所有其他条件相同(:
SkipNode *head = &first;
...
或者更好的是,一个名为(例如(SkipNodeList
的类,它处理管理和迭代SkipNode
列表的所有方面。
当然,无论如何,这一切都有点愚蠢,只需为此使用std::list
(或std::forward_list
(并从所有STL的好处中受益。
或者,您可以从其中之一派生以添加自己的功能(例如,互斥锁使列表线程安全或跟踪列表中当前元素的数量,如 @iMajuscule 所建议的那样(。
是的,有更好的方法:
前向声明Skipnode
,在BaseNode
中使用指向SkipNode
的指针,这样你就不必强制转换:
struct Skipnode;
struct Basenode {
Skipnode* next;
};
此外,为了说明Skipnode
从Basenode
继承的这种设计如何有意义(与评论中的讨论相关(,我们可以想象让一个成员在Basenode
计算下一个元素的数量(计算next
成员及其后继者中的元素(
- 如何读/写或遍历 std::array 中的特定元素范围?
- 是否有任何优雅的方式来遍历元素位置可以更改的列表?
- 遍历列表包含排除最后一个元素的内容
- 遍历并非所有元素都应具有值的元素
- boost multi_index - 如果元素类型仅支持移动语义,如何遍历它?
- C++ 如何以特定模式遍历矢量的不同集合元素
- 为什么 std::set 遍历所有元素的速度较慢?
- 遍历 STL 映射(集/多集)的最佳方法,同时元素可能会在循环期间被删除并重新插入?
- 循环遍历向量<string>并保持每个元素"count"时出现问题
- 如何遍历 QStack 对象的元素
- 在C 中的字符串向量的字符串元素中循环遍历所有字符
- 循环遍历向量中的所有(无序)元素对
- 如何在 c++ 列表中遍历固定数量的元素
- 如何遍历向量并知道元素的索引
- 在c++中遍历一个列表并在另一个列表中搜索每个元素
- 如何在不遍历优先级队列的情况下获取该队列的最后一个元素
- 使用另一个向量遍历向量的特定元素
- 使用 c while 循环遍历所有整数数组元素
- 遍历指向错误元素的列表
- 遍历结构元素向量