我在使用带有多个链表参数的递归链表功能时遇到麻烦。
到目前为止,我已经在下面提出了一个链接列表,并且效果很好。
def recursive_ll(ll):
if ll == None:
return None
elif ll.next == None:
return LN(ll.value)
else:
return_ll = LN(ll.value, recursive_ll(ll.next))
if return_ll.value == return_ll.next.value:
return_ll = return_ll.next
return return_ll
结果将是:
ll = list_to_ll(['x','g','f','n'])
print(str_ll(recursive_ll(ll)))
x->g->f->n->None
但是我真的对如何创建以多个链表作为参数的递归链表函数感到困惑。
例如,def recursive_ll(ll):将是def recursive_ll(ll,ll2):
返回的结果将是
ll = recursive_ll(['a','x','b','e'])
ll2 = recursive_ll(['d','f','m'])
a->d->x->f->b->m->e->None
再次从两个链接列表中合并以下所需的结果:
a->d->x->f->b->m->e->None
任何帮助/建议将不胜感激!
答案 0 :(得分:1)
您应该使用类而不是简单的函数作为助手。并接受任何可迭代项作为链表的来源。如果在链接列表类上实现迭代器,则将允许在任何可迭代列表和链接列表之间进行微不足道的转换。
链接列表类可以是:
class LL:
class iter:
def __init__(self, ll):
self.cur = ll.front
def __iter__(self):
return self
def __next__(self):
if self.cur is None:
raise StopIteration()
val = self.cur.value
self.cur = self.cur.next
return val
def __init__(self, l):
self.front = last = None
for v in l:
ln = LN(v)
if last is None:
self.front = ln
else:
last.next = ln
last = ln
def __str__(self):
answer = ''
for val in self.iter_elt():
answer += str(val) + '->'
return answer + 'None'
def __repr__(self):
return str(self.__class__) + ':' + str(self)
def __iter__(self):
return LL.iter(self)
这立即允许:
>>> print(LL('abcd'))
a->b->c->d->None
>>> list(LL('abcd'))
['a', 'b', 'c', 'd']
完成此操作后,您可以将“递归链接列表”声明为“链接列表”的子类,如果包含“链接列表”,则可以按合并顺序提取元素。
您应该首先在iter_elt
类中添加一个仅调用LL
的新方法iter
,然后在__str__
中使用该方法来简化子类化:
class LL:
...
def __str__(self):
answer = ''
for val in self.iter_elt():
answer += str(val) + '->'
return answer + 'None'
...
def iter_elt(self):
return self.__iter__()
因为现在,在RLL中重写iter_elt
就足够了,并构建一个迭代器,如果可能的话,它将反复扫描其子列表,反复调用iter_elt
,直到其他所有元素都用尽。代码可能是:
class RLL(LL):
class iter:
def __init__(self, rll):
self.iters = LL(i.iter_elt() if hasattr(i, 'iter_elt') else iter(i)
for i in rll)
self.cur = self.iters.front
self.prev = None
def __iter__(self):
return self
def __next__(self):
try:
elt = next(self.cur.value)
self.prev = self.cur
self.cur = self.cur.next
if self.cur is None:
self.cur = self.iters.front
self.prev = None
except StopIteration:
self.cur = self.cur.next
if self.cur is None:
if self.prev is None:
raise
self.cur = self.iters.front
self.prev = None
else:
if self.prev is None:
self.iters.front = self.cur
else:
self.prev.next = self.cur
elt = self.__next__()
return elt
def iter_elt(self):
return RLL.iter(self)
答案 1 :(得分:1)
我完全同意@Serge Ballesta的观点,即您应该创建一个LinkedList
类来执行此操作,这是按照您的操作方式进行操作的方法。
还请注意,它不是递归完成的,而是“ Python式的”。
from itertools import chain, zip_longest
class LN:
def __init__(self, value, next=None):
self.value = value
self.next = next
def list_to_ll(l):
if l == []:
return None
front = rear = LN(l[0])
for v in l[1:]:
rear.next = LN(v)
rear = rear.next
return front
def iterate(ll):
while ll is not None:
yield ll.value
ll = ll.next
def str_ll(ll):
return '->'.join(str(v) for v in iterate(ll)) + '->None'
def alternate(ll_1, ll_2):
_NULL = object()
chained = chain.from_iterable(zip_longest(iterate(ll_1), iterate(ll_2),
fillvalue=_NULL))
return list_to_ll(list(v for v in chained if v is not _NULL))
if __name__ == '__main__':
ll_1 = list_to_ll(['a','x','b','e'])
ll_2 = list_to_ll(['d','f','m'])
print(str_ll(alternate(ll_1, ll_2))) # -> a->d->x->f->b->m->e->None