2016-04-29 3 views
0

Во время моей степени бакалавра в CS я часто сталкивался с использованием рекурсивных структур данных. В C++ я всегда в конечном итоге с помощью указателей, чтобы мои структуры данных рекурсивных, так же как и то, что я хотел бы сделать в С.Рекурсивные структуры данных без использования указателей

Упрощенный пример может быть следующим:

struct Tree{ 
    int data; 
    struct Tree *left, *right; 
}; 

Однако, используя указатели, как правило, рискованная работа и требует много часов отладки и тестирования кода. Для этих ресусов я хотел бы знать, есть ли другой эффективный способ определения рекурсивных структур данных в C++.

В других языках программирования, как ржавчина, я видел такие вещи, как, что:

struct Node { 
    children: Vec<Node>, 
    node_type: NodeType, 
} 

Есть более безопасный и комфортабельный способ определения таких рекурсивных структур в C++. Одна из возможностей - использовать std :: Vector, но я не знаю о производительности метода.

+0

Вы можете сделать то же самое в C++, просто сделать дерево слева и справа, а не дерево. – Robinson

+7

@ Robinson, и это немедленно прекратит приложение - из-за бесконечного создания объекта Tree :) – hauron

+1

В некоторых случаях это на самом деле * преимущество * при использовании указателей, например, в древовидных структурах. Как вы иначе говорите, что у дерева нет детей? Нет никакого «нулевого» значения, которое может быть использовано для структур. –

ответ

2

В примере Rust используется вектор детей - это также может быть пустым.

В C++ переменная-член может быть объектом, указателем или ссылкой (опущена для простоты).

Поскольку объект узла не может быть использован непосредственно (это будет цикл бесконечно), и вы не хотите использовать указатель, ваши варианты:

  • использовать вектор, а также (хотя для бинарного дерева это не самый удобный тип - вы могли бы, однако ограничить его в коде всегда из двух элементов),

  • использовать карту (ключ может быть перечисление CHILD_LEFT, CHILD_RIGHT),

  • пересмотреть использование указателей, или еще лучше: умный указатели (это выглядит как хороший вариант использования для обычного unique_ptrs).

+0

Каким будет код при использовании ссылок? @Joachim Pileborg говорит, что Rust просто делает это. Однако вариант использования 'unique_ptrs' представляется для меня наиболее разумным. – zakum

+1

@zakum ему понадобится серия уродливых хаков (например, глобальный вектор дерева, три ctors for Tree: либо пустой, либо дочерний, либо оба дочерних элемента (поскольку вы не можете изменить ссылку, указанную в переменной после ее инициализации) и это просто создание ... как насчет удаления!). Я настоятельно рекомендую использовать unique_ptrs. Обратите внимание, что в C++, если исходные указатели * никогда не покидают объект, может быть безопасно использовать именно это (просто напишите надлежащий деструктор и избегайте выделения в конструкторе дерева). – hauron

+0

Благодарим вас за интерес и время. Я принимаю ваш ответ как лучший. В следующий раз я определенно попытаюсь использовать 'uniqe_ptr'. – zakum

2

Указатели причины используются, а не значения, потому что вы никогда не сможете определить свой struct, так как его размер будет бесконечно рекурсивным.

struct Tree{ 
    int data; 
    struct Tree left, right; 
}; 

Пренебрегая отступы и т.д., можно приблизить размер Tree в

sizeof(Tree) == sizeof(int) + sizeof(Tree) + sizeof(Tree) 
//      ^data   ^left   ^right 

но вы можете видеть, что с Tree имеет два члена Tree, и те члены сами имеют два Tree членов, и те, есть два члена Tree .... вы можете видеть, где это происходит.

+0

Я это знаю. Однако использование стиля C++ для выполнения вещей облегчит некоторые вещи, например «сбор мусора». Вот почему я пытаюсь найти способ определения рекурсивной структуры данных в C++. Если я недостаточно ясен, подумайте, как std :: Vector обрабатывает память самостоятельно. – zakum

Смежные вопросы