#julia
#джулия
Вопрос:
Я изучаю TAD, но я не очень разбираюсь в синтаксисе, поэтому мне слишком сложно создать единый список, но я понимаю, как это работает, например, TAD, пожалуйста, кто-нибудь может рассказать, как реализовать этот TAD (связанный список), с основными инструкциями и описаниемони
abstract type AbstractList{T} end
abstract type AbstractNode{T} end
mutable struct Nodo{T} <: AbstractNode{T}
value ::T
next ::Nodo{T}
Nodo{T}() where T =(x=new();x;x.next=x)
Nodo{T}(v,n) where T =new(v,n)
end
mutable struct LList{T} <: AbstractList{T}
first ::Nodo{T}
LList{T}() where T =new(Nodo{T}())
end
Lista=LList;
function Append(lista,value)
current=Nodo(value,new(Nodo()))
if Lista.size==0
lista.head=current
else
MyNode=Lista.first;
while MyNode.next!=nothing
MyNode=MyNode.next;
MyNode.next=current;
end
end
Lista.size =1
end
Append(Lista,2)
Я пытаюсь это сделать, но я не знаю, почему это не работает, я запутался, потому что я читал много сообщений об инструкциях, которые я использовал, но я совсем не понимаю Nodo{T}() where T =(x=new();x;x.next=x)
эту инструкцию, мне нужна помощь.
Комментарии:
1. Что означает «TAD»?
2. Я предположил, что ADT (абстрактный тип данных).
3. Ah, tipo abstracto de datos !
Ответ №1:
В вашем коде есть сочетание концепций, поэтому, чтобы помочь вам, я использую одну из них, чтобы показать вам, как вы можете реализовать свой связанный список. Вот код:
abstract type AbstractList{T} end
abstract type AbstractNode{T} end
mutable struct Nodo{T} <: AbstractNode{T}
value::T
next::Union{Nodo{T}, Nothing}
end
mutable struct LList{T} <: AbstractList{T}
head::Union{Nodo{T}, Nothing}
LList{T}() where T = new{T}(nothing)
end
function Base.push!(lista::LList, value)
new_nodo = Nodo(value, nothing)
if isnothing(lista.head)
lista.head = new_nodo
else
current_nodo = lista.head
while !isnothing(current_nodo.next)
current_nodo = current_nodo.next
end
current_nodo.next = new_nodo
end
return lista
end
и вот как вы можете его использовать:
julia> lista=LList{Int}()
LList{Int64}(nothing)
julia> push!(lista, 1)
LList{Int64}(Nodo{Int64}(1, nothing))
julia> push!(lista, 2)
LList{Int64}(Nodo{Int64}(1, Nodo{Int64}(2, nothing)))
julia> push!(lista, 3)
LList{Int64}(Nodo{Int64}(1, Nodo{Int64}(2, Nodo{Int64}(3, nothing))))
Некоторые комментарии:
- Я использую
Union
, чтобы показать, что объект может либо не содержать ссылки (Nothing
), либо какой-либо ссылки на следующий объект (Nodo{T}
) - В
LList{T}() where T = new{T}(nothing)
мы определяем только один внутренний конструктор, поскольку он не принимает аргументов, я используюnew{T}
его, доступный только во внутренних конструкторах, для создания экземпляраLList{T}
объекта со значением, равнымnothing
(поскольку у него еще нет узлов) - Я использую
Base.push!
, поскольку это стандартное имя функции для добавления элемента в коллекцию;Base.
необходимо для добавления метода в стандартную функцию; также поэтому позже я напишуlista::LList
, чтобы убедиться, что этот метод специфичен для вашегоLList{T}
типа - как вы можете видеть в коде, нет необходимости в «фиктивном» узле (как это было в вашем коде), поскольку вы просто отслеживаете конец списка, используя
nothing
значение
Я надеюсь, что начиная с этого момента вы сможете добавлять другие методы к своему LList
объекту.
Ответ №2:
Немного другая версия ответа Богумила заключается в использовании неопределенных полей.
abstract type AbstractList{T} end
abstract type AbstractNode{T} end
mutable struct Nodo{T} <: AbstractNode{T}
value::T
next::Nodo{T}
function Nodo(v::T) where T
n = new{T}()
n.value = v
return n
end
end
mutable struct LList{T} <: AbstractList{T}
head::Nodo{T}
LList{T}() where T = new{T}()
end
function Base.push!(lista::LList, value)
new_nodo = Nodo(value)
if isdefined(lista, :head)
current_nodo = lista.head
while isdefined(current_nodo, :next)
current_nodo = current_nodo.next
end
current_nodo.next = new_nodo
else
lista.head = new_nodo
end
return lista
end
и это работает так
julia> lista=LList{Int}()
LList{Int64}(#undef)
julia> push!(lista, 1)
LList{Int64}(Nodo{Int64}(1, #undef))
julia> push!(lista, 2)
LList{Int64}(Nodo{Int64}(1, Nodo{Int64}(2, #undef)))
julia> push!(lista, 3)
LList{Int64}(Nodo{Int64}(1, Nodo{Int64}(2, Nodo{Int64}(3, #undef))))
Этот подход не вводит поля объединения, но делает весь код более хрупким, поскольку вам нужно переключаться между nodo.next
isdefined(nodo, :next)
обозначениями и .