파이썬에서 링크 된 목록을 사용하는 가장 쉬운 방법은 무엇입니까? 구성표에서 링크 된 목록은로 간단히 정의됩니다 '(1 2 3 4 5)
. 파이썬의리스트 [1, 2, 3, 4, 5]
와 튜플 (1, 2, 3, 4, 5)
은 실제로는 링크 된리스트가 아니며, 링크 된리스트는 상수 시간 연결과 같은 훌륭한 속성을 가지고 있지 않으며 별도의 부분을 참조 할 수 있습니다. 그것들을 불변으로 만들고 작업하기가 정말 쉽습니다!
답변
다음은 Martin v. Löwis의 표현을 기반으로 한 일부 목록 함수입니다 .
cons = lambda el, lst: (el, lst)
mklist = lambda *args: reduce(lambda lst, el: cons(el, lst), reversed(args), None)
car = lambda lst: lst[0] if lst else lst
cdr = lambda lst: lst[1] if lst else lst
nth = lambda n, lst: nth(n-1, cdr(lst)) if n > 0 else car(lst)
length = lambda lst, count=0: length(cdr(lst), count+1) if lst else count
begin = lambda *args: args[-1]
display = lambda lst: begin(w("%s " % car(lst)), display(cdr(lst))) if lst else w("nil\n")
어디 w = sys.stdout.write
이중 연결 목록은 Raymond Hettinger의 정렬 된 세트 레시피 에서 널리 사용되지만 , 단일 연결 목록은 Python에서 실질적인 가치가 없습니다.
교육을 제외한 모든 문제에 대해 Python에서 단일 링크 목록을 사용한 적이 없습니다 .
Thomas Watnedal 은 훌륭한 교육 자료를 제안 했습니다 . 컴퓨터 과학자처럼 생각하는 방법, 17 장 : 연결 목록 :
연결된 목록은 다음 중 하나입니다.
- 없음으로 표시되는 빈 목록 또는
-
화물 객체 및 링크 된 목록에 대한 참조를 포함하는 노드.
class Node: def __init__(self, cargo=None, next=None): self.car = cargo self.cdr = next def __str__(self): return str(self.car) def display(lst): if lst: w("%s " % lst) display(lst.cdr) else: w("nil\n")
답변
일부 필요에 따라 deque 도 유용 할 수 있습니다. O (1) 비용으로 deque의 양쪽 끝에 항목을 추가하고 제거 할 수 있습니다.
from collections import deque
d = deque([1,2,3,4])
print d
for x in d:
print x
print d.pop(), d
답변
나는 다른 날에 이것을 썼다
#! /usr/bin/env python
class Node(object):
def __init__(self):
self.data = None # contains the data
self.next = None # contains the reference to the next node
class LinkedList:
def __init__(self):
self.cur_node = None
def add_node(self, data):
new_node = Node() # create a new node
new_node.data = data
new_node.next = self.cur_node # link the new node to the 'previous' node.
self.cur_node = new_node # set the current node to the new one.
def list_print(self):
node = self.cur_node # cant point to ll!
while node:
print node.data
node = node.next
ll = LinkedList()
ll.add_node(1)
ll.add_node(2)
ll.add_node(3)
ll.list_print()
답변
허용되는 답변은 다소 복잡합니다. 보다 표준적인 디자인은 다음과 같습니다.
L = LinkedList()
L.insert(1)
L.insert(1)
L.insert(2)
L.insert(4)
print L
L.clear()
print L
Thomas Watnedal이 권장 LinkedList
하는 간단한 C ++ 디자인 및 17 장 : 링크 된 목록을 기반으로 하는 간단한 클래스 입니다.
class Node:
def __init__(self, value = None, next = None):
self.value = value
self.next = next
def __str__(self):
return 'Node ['+str(self.value)+']'
class LinkedList:
def __init__(self):
self.first = None
self.last = None
def insert(self, x):
if self.first == None:
self.first = Node(x, None)
self.last = self.first
elif self.last == self.first:
self.last = Node(x, None)
self.first.next = self.last
else:
current = Node(x, None)
self.last.next = current
self.last = current
def __str__(self):
if self.first != None:
current = self.first
out = 'LinkedList [\n' +str(current.value) +'\n'
while current.next != None:
current = current.next
out += str(current.value) + '\n'
return out + ']'
return 'LinkedList []'
def clear(self):
self.__init__()
답변
변경 불가능한 목록은 2 개의 튜플을 통해 가장 잘 표현되며 없음은 NIL을 나타냅니다. 이러한 목록의 간단한 공식화를 위해이 함수를 사용할 수 있습니다.
def mklist(*args):
result = None
for element in reversed(args):
result = (element, result)
return result
이러한 목록으로 작업하려면 메소드를 도입하는 것보다 LISP 함수의 전체 컬렉션 (즉, 첫 번째, 두 번째, n 번째 등)을 제공하고 싶습니다.
답변
다음은 파이썬의 시퀀스 유형과 비슷한 인터페이스를 가진 약간 더 복잡한 버전의 링크 된 목록 클래스입니다 (예 : 인덱싱, 슬라이싱, 임의 시퀀스와의 연결 등 지원). O (1) 접두어를 가져야하며, 튜플과 상호 교환없이 사용할 수 있어야하며 데이터를 복사하지 않으면 데이터를 복사하지 않습니다.
파이썬 클래스는 분명히 조금 더 무겁기 때문에 lisp cons 셀만큼 공간이나 시간 효율적이지 않을 것입니다 ( “__slots__ = '_head','_tail'
메모리 사용을 줄이기 위해 “로 있습니다). 그러나 원하는 큰 O 성능 특성을 갖습니다.
사용 예 :
>>> l = LinkedList([1,2,3,4])
>>> l
LinkedList([1, 2, 3, 4])
>>> l.head, l.tail
(1, LinkedList([2, 3, 4]))
# Prepending is O(1) and can be done with:
LinkedList.cons(0, l)
LinkedList([0, 1, 2, 3, 4])
# Or prepending arbitrary sequences (Still no copy of l performed):
[-1,0] + l
LinkedList([-1, 0, 1, 2, 3, 4])
# Normal list indexing and slice operations can be performed.
# Again, no copy is made unless needed.
>>> l[1], l[-1], l[2:]
(2, 4, LinkedList([3, 4]))
>>> assert l[2:] is l.next.next
# For cases where the slice stops before the end, or uses a
# non-contiguous range, we do need to create a copy. However
# this should be transparent to the user.
>>> LinkedList(range(100))[-10::2]
LinkedList([90, 92, 94, 96, 98])
이행:
import itertools
class LinkedList(object):
"""Immutable linked list class."""
def __new__(cls, l=[]):
if isinstance(l, LinkedList): return l # Immutable, so no copy needed.
i = iter(l)
try:
head = i.next()
except StopIteration:
return cls.EmptyList # Return empty list singleton.
tail = LinkedList(i)
obj = super(LinkedList, cls).__new__(cls)
obj._head = head
obj._tail = tail
return obj
@classmethod
def cons(cls, head, tail):
ll = cls([head])
if not isinstance(tail, cls):
tail = cls(tail)
ll._tail = tail
return ll
# head and tail are not modifiable
@property
def head(self): return self._head
@property
def tail(self): return self._tail
def __nonzero__(self): return True
def __len__(self):
return sum(1 for _ in self)
def __add__(self, other):
other = LinkedList(other)
if not self: return other # () + l = l
start=l = LinkedList(iter(self)) # Create copy, as we'll mutate
while l:
if not l._tail: # Last element?
l._tail = other
break
l = l._tail
return start
def __radd__(self, other):
return LinkedList(other) + self
def __iter__(self):
x=self
while x:
yield x.head
x=x.tail
def __getitem__(self, idx):
"""Get item at specified index"""
if isinstance(idx, slice):
# Special case: Avoid constructing a new list, or performing O(n) length
# calculation for slices like l[3:]. Since we're immutable, just return
# the appropriate node. This becomes O(start) rather than O(n).
# We can't do this for more complicated slices however (eg [l:4]
start = idx.start or 0
if (start >= 0) and (idx.stop is None) and (idx.step is None or idx.step == 1):
no_copy_needed=True
else:
length = len(self) # Need to calc length.
start, stop, step = idx.indices(length)
no_copy_needed = (stop == length) and (step == 1)
if no_copy_needed:
l = self
for i in range(start):
if not l: break # End of list.
l=l.tail
return l
else:
# We need to construct a new list.
if step < 1: # Need to instantiate list to deal with -ve step
return LinkedList(list(self)[start:stop:step])
else:
return LinkedList(itertools.islice(iter(self), start, stop, step))
else:
# Non-slice index.
if idx < 0: idx = len(self)+idx
if not self: raise IndexError("list index out of range")
if idx == 0: return self.head
return self.tail[idx-1]
def __mul__(self, n):
if n <= 0: return Nil
l=self
for i in range(n-1): l += self
return l
def __rmul__(self, n): return self * n
# Ideally we should compute the has ourselves rather than construct
# a temporary tuple as below. I haven't impemented this here
def __hash__(self): return hash(tuple(self))
def __eq__(self, other): return self._cmp(other) == 0
def __ne__(self, other): return not self == other
def __lt__(self, other): return self._cmp(other) < 0
def __gt__(self, other): return self._cmp(other) > 0
def __le__(self, other): return self._cmp(other) <= 0
def __ge__(self, other): return self._cmp(other) >= 0
def _cmp(self, other):
"""Acts as cmp(): -1 for self<other, 0 for equal, 1 for greater"""
if not isinstance(other, LinkedList):
return cmp(LinkedList,type(other)) # Arbitrary ordering.
A, B = iter(self), iter(other)
for a,b in itertools.izip(A,B):
if a<b: return -1
elif a > b: return 1
try:
A.next()
return 1 # a has more items.
except StopIteration: pass
try:
B.next()
return -1 # b has more items.
except StopIteration: pass
return 0 # Lists are equal
def __repr__(self):
return "LinkedList([%s])" % ', '.join(map(repr,self))
class EmptyList(LinkedList):
"""A singleton representing an empty list."""
def __new__(cls):
return object.__new__(cls)
def __iter__(self): return iter([])
def __nonzero__(self): return False
@property
def head(self): raise IndexError("End of list")
@property
def tail(self): raise IndexError("End of list")
# Create EmptyList singleton
LinkedList.EmptyList = EmptyList()
del EmptyList
답변
llist — Python의 링크 된 목록 데이터 유형
llist 모듈은 연결된 목록 데이터 구조를 구현합니다. 이중 연결 목록, 즉 dllist
단일 연결 데이터 구조를 지원 sllist
합니다.
dllist 객체
이 개체는 이중 연결 목록 데이터 구조를 나타냅니다.
first
dllistnode
목록의 첫 번째 개체 None
목록이 비어있는 경우
last
dllistnode
목록의 마지막 개체 목록이 비어있는 경우 없음
dllist 객체는 다음 방법도 지원합니다.
append(x)
x
목록의 오른쪽에 추가 하고 삽입 된 상태로 반환 dllistnode
합니다.
appendleft(x)
x
목록의 왼쪽에 추가 하고 insert를 반환 dllistnode
합니다.
appendright(x)
x
목록의 오른쪽에 추가 하고 삽입 된 상태로 반환 dllistnode
합니다.
clear()
목록에서 모든 노드를 제거하십시오.
extend(iterable)
iterable
목록의 오른쪽 에서 요소를 추가 하십시오.
extendleft(iterable)
iterable
목록의 왼쪽 에서 요소를 추가 하십시오.
extendright(iterable)
iterable
목록의 오른쪽 에서 요소를 추가 하십시오.
insert(x[, before])
지정되지 않은 x
경우 목록의 오른쪽에 추가 before
하거나 x
의 왼쪽에 삽입 하십시오 dllistnode before
. 삽입 삽입 dllistnode
.
nodeat(index)
반환 노드 (유형의 dllistnode
)에서 index
.
pop()
목록의 오른쪽에서 요소 값을 제거하고 반환하십시오.
popleft()
목록의 왼쪽에서 요소 값을 제거하고 반환하십시오.
popright()
목록의 오른쪽에서 요소의 값을 제거하고 반환
remove(node)
없애다 node
목록에서 하고 저장된 요소를 리턴하십시오.
dllistnode
사물
수업 llist.dllistnode([value])
다음과 같이 초기화 된 새 이중 연결 목록 노드를 반환합니다 (선택 사항). value
.
dllistnode
객체는 다음과 같은 속성을 제공합니다.
next
목록의 다음 노드 이 속성은 읽기 전용입니다.
prev
목록의 이전 노드 이 속성은 읽기 전용입니다.
value
이 노드에 저장된 값.
이 참조에서 컴파일
슬릿
클래스 llist.sllist([iterable])
반환의 요소로 초기화 된 새로운 단일 연결리스트 iterable
. iterable을 지정하지 않으면 새 항목 sllist
이 비어 있습니다.
이 sllist
개체에 대해 유사한 속성 및 작업 집합이 정의되어 있습니다. 자세한 내용은이 참조를 참조하십시오.