问题:Python链表
在python中使用链表的最简单方法是什么?在方案中,链表仅由定义'(1 2 3 4 5)
。实际上,Python的list [1, 2, 3, 4, 5]
和tuple (1, 2, 3, 4, 5)
不是链表,而链表具有一些不错的属性,例如恒定时间串联,并且能够引用其中的各个部分。使它们一成不变,并且它们真的很容易使用!
What’s the easiest way to use a linked list in python? In scheme, a linked list is defined simply by '(1 2 3 4 5)
. Python’s lists, [1, 2, 3, 4, 5]
, and tuples, (1, 2, 3, 4, 5)
, are not, in fact, linked lists, and linked lists have some nice properties such as constant-time concatenation, and being able to reference separate parts of them. Make them immutable and they are really easy to work with!
回答 0
以下是一些基于Martin诉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")
Here is some list functions based on Martin v. Löwis’s representation:
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")
where w = sys.stdout.write
Although doubly linked lists are famously used in Raymond Hettinger’s ordered set recipe, singly linked lists have no practical value in Python.
I’ve never used a singly linked list in Python for any problem except educational.
Thomas Watnedal suggested a good educational resource How to Think Like a Computer Scientist, Chapter 17: Linked lists:
A linked list is either:
- the empty list, represented by None, or
a node that contains a cargo object and a reference to a linked list.
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")
回答 1
对于某些需求,双端队列也可能有用。您可以在双端队列的两端添加和删除项,费用为O(1)。
from collections import deque
d = deque([1,2,3,4])
print d
for x in d:
print x
print d.pop(), d
For some needs, a deque may also be useful. You can add and remove items on both ends of a deque at O(1) cost.
from collections import deque
d = deque([1,2,3,4])
print d
for x in d:
print x
print d.pop(), d
回答 2
我前几天写的
#! /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()
I wrote this up the other day
#! /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()
回答 3
公认的答案相当复杂。这是一个更标准的设计:
L = LinkedList()
L.insert(1)
L.insert(1)
L.insert(2)
L.insert(4)
print L
L.clear()
print L
这是一个简单的LinkedList
类,基于简单的C ++设计和Thomas Watnedal推荐的第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__()
The accepted answer is rather complicated. Here is a more standard design:
L = LinkedList()
L.insert(1)
L.insert(1)
L.insert(2)
L.insert(4)
print L
L.clear()
print L
It is a simple LinkedList
class based on the straightforward C++ design and Chapter 17: Linked lists, as recommended by Thomas Watnedal.
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__()
回答 4
不可变列表最好用两元组表示,而None表示NIL。为了使这样的列表变得简单,可以使用以下功能:
def mklist(*args):
result = None
for element in reversed(args):
result = (element, result)
return result
为了处理这样的列表,我宁愿提供LISP函数的全部集合(即,第一,第二,第n等),而不是介绍方法。
Immutable lists are best represented through two-tuples, with None representing NIL. To allow simple formulation of such lists, you can use this function:
def mklist(*args):
result = None
for element in reversed(args):
result = (element, result)
return result
To work with such lists, I’d rather provide the whole collection of LISP functions (i.e. first, second, nth, etc), than introducing methods.
回答 5
这是链表类的稍微复杂一点的版本,具有与python的序列类型相似的接口(即,支持索引,切片,与任意序列的串联等)。它应该有O(1)前缀,除非需要,否则不要复制数据,并且可以与元组互换使用。
它不会像lisp cons单元那样节省空间或时间,因为python类显然要重得多(您可以使用“ __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
Here’s a slightly more complex version of a linked list class, with a similar interface to python’s sequence types (ie. supports indexing, slicing, concatenation with arbitrary sequences etc). It should have O(1) prepend, doesn’t copy data unless it needs to and can be used pretty interchangably with tuples.
It won’t be as space or time efficient as lisp cons cells, as python classes are obviously a bit more heavyweight (You could improve things slightly with “__slots__ = '_head','_tail'
” to reduce memory usage). It will have the desired big O performance characteristics however.
Example of usage:
>>> 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])
Implementation:
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
回答 6
llist — Python的链接列表数据类型
llist模块实现链接列表数据结构。它支持双向链表,即dllist
单链数据结构sllist
。
dllist对象
该对象表示双向链表数据结构。
first
dllistnode
列表中的第一个对象。None
如果列表为空。
last
dllistnode
列表中的最后一个对象。如果列表为空,则无。
dllist对象还支持以下方法:
append(x)
添加x
到列表的右侧,然后返回insert dllistnode
。
appendleft(x)
添加x
到列表的左侧,然后返回insert dllistnode
。
appendright(x)
添加x
到列表的右侧,然后返回insert 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
存储在此节点中的值。
从此参考资料编译
清单
class llist.sllist([iterable])
返回一个新的单链接列表,该列表使用中的元素初始化iterable
。如果未指定iterable,则新sllist
值为空。
为此sllist
对象定义了一组相似的属性和操作。有关更多信息,请参见此参考。
llist — Linked list datatypes for Python
llist module implements linked list data structures. It supports a doubly linked list, i.e. dllist
and a singly linked data structure sllist
.
dllist objects
This object represents a doubly linked list data structure.
first
First dllistnode
object in the list. None
if list is empty.
last
Last dllistnode
object in the list. None if list is empty.
dllist objects also support the following methods:
append(x)
Add x
to the right side of the list and return inserted dllistnode
.
appendleft(x)
Add x
to the left side of the list and return inserted dllistnode
.
appendright(x)
Add x
to the right side of the list and return inserted dllistnode
.
clear()
Remove all nodes from the list.
extend(iterable)
Append elements from iterable
to the right side of the list.
extendleft(iterable)
Append elements from iterable
to the left side of the list.
extendright(iterable)
Append elements from iterable
to the right side of the list.
insert(x[, before])
Add x
to the right side of the list if before
is not specified, or insert x
to the left side of dllistnode before
. Return inserted dllistnode
.
nodeat(index)
Return node (of type dllistnode
) at index
.
pop()
Remove and return an element’s value from the right side of the list.
popleft()
Remove and return an element’s value from the left side of the list.
popright()
Remove and return an element’s value from the right side of the list
remove(node)
Remove node
from the list and return the element which was stored in it.
dllistnode
objects
class llist.dllistnode([value])
Return a new doubly linked list node, initialized (optionally) with value
.
dllistnode
objects provide the following attributes:
next
Next node in the list. This attribute is read-only.
prev
Previous node in the list. This attribute is read-only.
value
Value stored in this node.
Compiled from this reference
sllist
class llist.sllist([iterable])
Return a new singly linked list initialized with elements from iterable
. If iterable is not specified, the new sllist
is empty.
A similar set of attributes and operations are defined for this sllist
object. See this reference for more information.
回答 7
class Node(object):
def __init__(self, data=None, next=None):
self.data = data
self.next = next
def setData(self, data):
self.data = data
return self.data
def setNext(self, next):
self.next = next
def getNext(self):
return self.next
def hasNext(self):
return self.next != None
class singleLinkList(object):
def __init__(self):
self.head = None
def isEmpty(self):
return self.head == None
def insertAtBeginning(self, data):
newNode = Node()
newNode.setData(data)
if self.listLength() == 0:
self.head = newNode
else:
newNode.setNext(self.head)
self.head = newNode
def insertAtEnd(self, data):
newNode = Node()
newNode.setData(data)
current = self.head
while current.getNext() != None:
current = current.getNext()
current.setNext(newNode)
def listLength(self):
current = self.head
count = 0
while current != None:
count += 1
current = current.getNext()
return count
def print_llist(self):
current = self.head
print("List Start.")
while current != None:
print(current.getData())
current = current.getNext()
print("List End.")
if __name__ == '__main__':
ll = singleLinkList()
ll.insertAtBeginning(55)
ll.insertAtEnd(56)
ll.print_llist()
print(ll.listLength())
class Node(object):
def __init__(self, data=None, next=None):
self.data = data
self.next = next
def setData(self, data):
self.data = data
return self.data
def setNext(self, next):
self.next = next
def getNext(self):
return self.next
def hasNext(self):
return self.next != None
class singleLinkList(object):
def __init__(self):
self.head = None
def isEmpty(self):
return self.head == None
def insertAtBeginning(self, data):
newNode = Node()
newNode.setData(data)
if self.listLength() == 0:
self.head = newNode
else:
newNode.setNext(self.head)
self.head = newNode
def insertAtEnd(self, data):
newNode = Node()
newNode.setData(data)
current = self.head
while current.getNext() != None:
current = current.getNext()
current.setNext(newNode)
def listLength(self):
current = self.head
count = 0
while current != None:
count += 1
current = current.getNext()
return count
def print_llist(self):
current = self.head
print("List Start.")
while current != None:
print(current.getData())
current = current.getNext()
print("List End.")
if __name__ == '__main__':
ll = singleLinkList()
ll.insertAtBeginning(55)
ll.insertAtEnd(56)
ll.print_llist()
print(ll.listLength())
回答 8
我基于Nick Stinemates这个附加功能
def add_node_at_end(self, data):
new_node = Node()
node = self.curr_node
while node:
if node.next == None:
node.next = new_node
new_node.next = None
new_node.data = data
node = node.next
他已经在开始时添加了新节点的方法中,而我看到了很多实现通常在末尾添加了新节点的实现,但是无论如何,这都很有趣。
I based this additional function on Nick Stinemates
def add_node_at_end(self, data):
new_node = Node()
node = self.curr_node
while node:
if node.next == None:
node.next = new_node
new_node.next = None
new_node.data = data
node = node.next
The method he has adds the new node at the beginning while I have seen a lot of implementations which usually add a new node at the end but whatever, it is fun to do.
回答 9
以下是我想出的。在此线程中,它类似于Riccardo C.的,但它按顺序打印数字而不是反向打印。我还使LinkedList对象成为Python迭代器,以便像打印普通Python列表一样打印出列表。
class Node:
def __init__(self, data=None):
self.data = data
self.next = None
def __str__(self):
return str(self.data)
class LinkedList:
def __init__(self):
self.head = None
self.curr = None
self.tail = None
def __iter__(self):
return self
def next(self):
if self.head and not self.curr:
self.curr = self.head
return self.curr
elif self.curr.next:
self.curr = self.curr.next
return self.curr
else:
raise StopIteration
def append(self, data):
n = Node(data)
if not self.head:
self.head = n
self.tail = n
else:
self.tail.next = n
self.tail = self.tail.next
# Add 5 nodes
ll = LinkedList()
for i in range(1, 6):
ll.append(i)
# print out the list
for n in ll:
print n
"""
Example output:
$ python linked_list.py
1
2
3
4
5
"""
The following is what I came up with. It’s similer to Riccardo C.’s, in this thread, except it prints the numbers in order instead of in reverse. I also made the LinkedList object a Python Iterator in order to print the list out like you would a normal Python list.
class Node:
def __init__(self, data=None):
self.data = data
self.next = None
def __str__(self):
return str(self.data)
class LinkedList:
def __init__(self):
self.head = None
self.curr = None
self.tail = None
def __iter__(self):
return self
def next(self):
if self.head and not self.curr:
self.curr = self.head
return self.curr
elif self.curr.next:
self.curr = self.curr.next
return self.curr
else:
raise StopIteration
def append(self, data):
n = Node(data)
if not self.head:
self.head = n
self.tail = n
else:
self.tail.next = n
self.tail = self.tail.next
# Add 5 nodes
ll = LinkedList()
for i in range(1, 6):
ll.append(i)
# print out the list
for n in ll:
print n
"""
Example output:
$ python linked_list.py
1
2
3
4
5
"""
回答 10
我只是做这个作为一个有趣的玩具。只要您不使用下划线前缀的方法,它就应该是不变的,并且它实现了Python魔术,例如indexing和len
。
I just did this as a fun toy. It should be immutable as long as you don’t touch the underscore-prefixed methods, and it implements a bunch of Python magic like indexing and len
.
回答 11
使用不可变链表时,请考虑直接使用Python的元组。
ls = (1, 2, 3, 4, 5)
def first(ls): return ls[0]
def rest(ls): return ls[1:]
真的很容易,您可以保留其他函数,例如len(ls),x in ls等。
When using immutable linked lists, consider using Python’s tuple directly.
ls = (1, 2, 3, 4, 5)
def first(ls): return ls[0]
def rest(ls): return ls[1:]
Its really that ease, and you get to keep the additional funcitons like len(ls), x in ls, etc.
回答 12
class LL(object):
def __init__(self,val):
self.val = val
self.next = None
def pushNodeEnd(self,top,val):
if top is None:
top.val=val
top.next=None
else:
tmp=top
while (tmp.next != None):
tmp=tmp.next
newNode=LL(val)
newNode.next=None
tmp.next=newNode
def pushNodeFront(self,top,val):
if top is None:
top.val=val
top.next=None
else:
newNode=LL(val)
newNode.next=top
top=newNode
def popNodeFront(self,top):
if top is None:
return
else:
sav=top
top=top.next
return sav
def popNodeEnd(self,top):
if top is None:
return
else:
tmp=top
while (tmp.next != None):
prev=tmp
tmp=tmp.next
prev.next=None
return tmp
top=LL(10)
top.pushNodeEnd(top, 20)
top.pushNodeEnd(top, 30)
pop=top.popNodeEnd(top)
print (pop.val)
class LL(object):
def __init__(self,val):
self.val = val
self.next = None
def pushNodeEnd(self,top,val):
if top is None:
top.val=val
top.next=None
else:
tmp=top
while (tmp.next != None):
tmp=tmp.next
newNode=LL(val)
newNode.next=None
tmp.next=newNode
def pushNodeFront(self,top,val):
if top is None:
top.val=val
top.next=None
else:
newNode=LL(val)
newNode.next=top
top=newNode
def popNodeFront(self,top):
if top is None:
return
else:
sav=top
top=top.next
return sav
def popNodeEnd(self,top):
if top is None:
return
else:
tmp=top
while (tmp.next != None):
prev=tmp
tmp=tmp.next
prev.next=None
return tmp
top=LL(10)
top.pushNodeEnd(top, 20)
top.pushNodeEnd(top, 30)
pop=top.popNodeEnd(top)
print (pop.val)
回答 13
I’ve put a Python 2.x and 3.x singly-linked list class at https://pypi.python.org/pypi/linked_list_mod/
It’s tested with CPython 2.7, CPython 3.4, Pypy 2.3.1, Pypy3 2.3.1, and Jython 2.7b2, and comes with a nice automated test suite.
It also includes LIFO and FIFO classes.
They aren’t immutable though.
回答 14
class LinkedStack:
'''LIFO Stack implementation using a singly linked list for storage.'''
_ToList = []
#---------- nested _Node class -----------------------------
class _Node:
'''Lightweight, nonpublic class for storing a singly linked node.'''
__slots__ = '_element', '_next' #streamline memory usage
def __init__(self, element, next):
self._element = element
self._next = next
#--------------- stack methods ---------------------------------
def __init__(self):
'''Create an empty stack.'''
self._head = None
self._size = 0
def __len__(self):
'''Return the number of elements in the stack.'''
return self._size
def IsEmpty(self):
'''Return True if the stack is empty'''
return self._size == 0
def Push(self,e):
'''Add element e to the top of the Stack.'''
self._head = self._Node(e, self._head) #create and link a new node
self._size +=1
self._ToList.append(e)
def Top(self):
'''Return (but do not remove) the element at the top of the stack.
Raise exception if the stack is empty
'''
if self.IsEmpty():
raise Exception('Stack is empty')
return self._head._element #top of stack is at head of list
def Pop(self):
'''Remove and return the element from the top of the stack (i.e. LIFO).
Raise exception if the stack is empty
'''
if self.IsEmpty():
raise Exception('Stack is empty')
answer = self._head._element
self._head = self._head._next #bypass the former top node
self._size -=1
self._ToList.remove(answer)
return answer
def Count(self):
'''Return how many nodes the stack has'''
return self.__len__()
def Clear(self):
'''Delete all nodes'''
for i in range(self.Count()):
self.Pop()
def ToList(self):
return self._ToList
class LinkedStack:
'''LIFO Stack implementation using a singly linked list for storage.'''
_ToList = []
#---------- nested _Node class -----------------------------
class _Node:
'''Lightweight, nonpublic class for storing a singly linked node.'''
__slots__ = '_element', '_next' #streamline memory usage
def __init__(self, element, next):
self._element = element
self._next = next
#--------------- stack methods ---------------------------------
def __init__(self):
'''Create an empty stack.'''
self._head = None
self._size = 0
def __len__(self):
'''Return the number of elements in the stack.'''
return self._size
def IsEmpty(self):
'''Return True if the stack is empty'''
return self._size == 0
def Push(self,e):
'''Add element e to the top of the Stack.'''
self._head = self._Node(e, self._head) #create and link a new node
self._size +=1
self._ToList.append(e)
def Top(self):
'''Return (but do not remove) the element at the top of the stack.
Raise exception if the stack is empty
'''
if self.IsEmpty():
raise Exception('Stack is empty')
return self._head._element #top of stack is at head of list
def Pop(self):
'''Remove and return the element from the top of the stack (i.e. LIFO).
Raise exception if the stack is empty
'''
if self.IsEmpty():
raise Exception('Stack is empty')
answer = self._head._element
self._head = self._head._next #bypass the former top node
self._size -=1
self._ToList.remove(answer)
return answer
def Count(self):
'''Return how many nodes the stack has'''
return self.__len__()
def Clear(self):
'''Delete all nodes'''
for i in range(self.Count()):
self.Pop()
def ToList(self):
return self._ToList
回答 15
链表类
class LinkedStack:
# Nested Node Class
class Node:
def __init__(self, element, next):
self.__element = element
self.__next = next
def get_next(self):
return self.__next
def get_element(self):
return self.__element
def __init__(self):
self.head = None
self.size = 0
self.data = []
def __len__(self):
return self.size
def __str__(self):
return str(self.data)
def is_empty(self):
return self.size == 0
def push(self, e):
newest = self.Node(e, self.head)
self.head = newest
self.size += 1
self.data.append(newest)
def top(self):
if self.is_empty():
raise Empty('Stack is empty')
return self.head.__element
def pop(self):
if self.is_empty():
raise Empty('Stack is empty')
answer = self.head.element
self.head = self.head.next
self.size -= 1
return answer
用法
from LinkedStack import LinkedStack
x = LinkedStack()
x.push(10)
x.push(25)
x.push(55)
for i in range(x.size - 1, -1, -1):
print '|', x.data[i].get_element(), '|' ,
#next object
if x.data[i].get_next() == None:
print '--> None'
else:
print x.data[i].get_next().get_element(), '-|----> ',
输出量
| 55 | 25 -|----> | 25 | 10 -|----> | 10 | --> None
Linked List Class
class LinkedStack:
# Nested Node Class
class Node:
def __init__(self, element, next):
self.__element = element
self.__next = next
def get_next(self):
return self.__next
def get_element(self):
return self.__element
def __init__(self):
self.head = None
self.size = 0
self.data = []
def __len__(self):
return self.size
def __str__(self):
return str(self.data)
def is_empty(self):
return self.size == 0
def push(self, e):
newest = self.Node(e, self.head)
self.head = newest
self.size += 1
self.data.append(newest)
def top(self):
if self.is_empty():
raise Empty('Stack is empty')
return self.head.__element
def pop(self):
if self.is_empty():
raise Empty('Stack is empty')
answer = self.head.element
self.head = self.head.next
self.size -= 1
return answer
Usage
from LinkedStack import LinkedStack
x = LinkedStack()
x.push(10)
x.push(25)
x.push(55)
for i in range(x.size - 1, -1, -1):
print '|', x.data[i].get_element(), '|' ,
#next object
if x.data[i].get_next() == None:
print '--> None'
else:
print x.data[i].get_next().get_element(), '-|----> ',
Output
| 55 | 25 -|----> | 25 | 10 -|----> | 10 | --> None
回答 16
这是我的简单实现:
class Node:
def __init__(self):
self.data = None
self.next = None
def __str__(self):
return "Data %s: Next -> %s"%(self.data, self.next)
class LinkedList:
def __init__(self):
self.head = Node()
self.curNode = self.head
def insertNode(self, data):
node = Node()
node.data = data
node.next = None
if self.head.data == None:
self.head = node
self.curNode = node
else:
self.curNode.next = node
self.curNode = node
def printList(self):
print self.head
l = LinkedList()
l.insertNode(1)
l.insertNode(2)
l.insertNode(34)
输出:
Data 1: Next -> Data 2: Next -> Data 34: Next -> Data 4: Next -> None
Here is my simple implementation:
class Node:
def __init__(self):
self.data = None
self.next = None
def __str__(self):
return "Data %s: Next -> %s"%(self.data, self.next)
class LinkedList:
def __init__(self):
self.head = Node()
self.curNode = self.head
def insertNode(self, data):
node = Node()
node.data = data
node.next = None
if self.head.data == None:
self.head = node
self.curNode = node
else:
self.curNode.next = node
self.curNode = node
def printList(self):
print self.head
l = LinkedList()
l.insertNode(1)
l.insertNode(2)
l.insertNode(34)
Output:
Data 1: Next -> Data 2: Next -> Data 34: Next -> Data 4: Next -> None
回答 17
这是我的解决方案:
实作
class Node:
def __init__(self, initdata):
self.data = initdata
self.next = None
def get_data(self):
return self.data
def set_data(self, data):
self.data = data
def get_next(self):
return self.next
def set_next(self, node):
self.next = node
# ------------------------ Link List class ------------------------------- #
class LinkList:
def __init__(self):
self.head = None
def is_empty(self):
return self.head == None
def traversal(self, data=None):
node = self.head
index = 0
found = False
while node is not None and not found:
if node.get_data() == data:
found = True
else:
node = node.get_next()
index += 1
return (node, index)
def size(self):
_, count = self.traversal(None)
return count
def search(self, data):
node, _ = self.traversal(data)
return node
def add(self, data):
node = Node(data)
node.set_next(self.head)
self.head = node
def remove(self, data):
previous_node = None
current_node = self.head
found = False
while current_node is not None and not found:
if current_node.get_data() == data:
found = True
if previous_node:
previous_node.set_next(current_node.get_next())
else:
self.head = current_node
else:
previous_node = current_node
current_node = current_node.get_next()
return found
用法
link_list = LinkList()
link_list.add(10)
link_list.add(20)
link_list.add(30)
link_list.add(40)
link_list.add(50)
link_list.size()
link_list.search(30)
link_list.remove(20)
最初的实施思路
http://interactivepython.org/runestone/static/pythonds/BasicDS/ImplementinganUnorderedListLinkedLists.html
Here is my solution:
Implementation
class Node:
def __init__(self, initdata):
self.data = initdata
self.next = None
def get_data(self):
return self.data
def set_data(self, data):
self.data = data
def get_next(self):
return self.next
def set_next(self, node):
self.next = node
# ------------------------ Link List class ------------------------------- #
class LinkList:
def __init__(self):
self.head = None
def is_empty(self):
return self.head == None
def traversal(self, data=None):
node = self.head
index = 0
found = False
while node is not None and not found:
if node.get_data() == data:
found = True
else:
node = node.get_next()
index += 1
return (node, index)
def size(self):
_, count = self.traversal(None)
return count
def search(self, data):
node, _ = self.traversal(data)
return node
def add(self, data):
node = Node(data)
node.set_next(self.head)
self.head = node
def remove(self, data):
previous_node = None
current_node = self.head
found = False
while current_node is not None and not found:
if current_node.get_data() == data:
found = True
if previous_node:
previous_node.set_next(current_node.get_next())
else:
self.head = current_node
else:
previous_node = current_node
current_node = current_node.get_next()
return found
Usage
link_list = LinkList()
link_list.add(10)
link_list.add(20)
link_list.add(30)
link_list.add(40)
link_list.add(50)
link_list.size()
link_list.search(30)
link_list.remove(20)
Original Implementation Idea
http://interactivepython.org/runestone/static/pythonds/BasicDS/ImplementinganUnorderedListLinkedLists.html
回答 18
我认为下面的实现可以很好地满足要求。
'''singly linked lists, by Yingjie Lan, December 1st, 2011'''
class linkst:
'''Singly linked list, with pythonic features.
The list has pointers to both the first and the last node.'''
__slots__ = ['data', 'next'] #memory efficient
def __init__(self, iterable=(), data=None, next=None):
'''Provide an iterable to make a singly linked list.
Set iterable to None to make a data node for internal use.'''
if iterable is not None:
self.data, self.next = self, None
self.extend(iterable)
else: #a common node
self.data, self.next = data, next
def empty(self):
'''test if the list is empty'''
return self.next is None
def append(self, data):
'''append to the end of list.'''
last = self.data
self.data = last.next = linkst(None, data)
#self.data = last.next
def insert(self, data, index=0):
'''insert data before index.
Raise IndexError if index is out of range'''
curr, cat = self, 0
while cat < index and curr:
curr, cat = curr.next, cat+1
if index<0 or not curr:
raise IndexError(index)
new = linkst(None, data, curr.next)
if curr.next is None: self.data = new
curr.next = new
def reverse(self):
'''reverse the order of list in place'''
current, prev = self.next, None
while current: #what if list is empty?
next = current.next
current.next = prev
prev, current = current, next
if self.next: self.data = self.next
self.next = prev
def delete(self, index=0):
'''remvoe the item at index from the list'''
curr, cat = self, 0
while cat < index and curr.next:
curr, cat = curr.next, cat+1
if index<0 or not curr.next:
raise IndexError(index)
curr.next = curr.next.next
if curr.next is None: #tail
self.data = curr #current == self?
def remove(self, data):
'''remove first occurrence of data.
Raises ValueError if the data is not present.'''
current = self
while current.next: #node to be examined
if data == current.next.data: break
current = current.next #move on
else: raise ValueError(data)
current.next = current.next.next
if current.next is None: #tail
self.data = current #current == self?
def __contains__(self, data):
'''membership test using keyword 'in'.'''
current = self.next
while current:
if data == current.data:
return True
current = current.next
return False
def __iter__(self):
'''iterate through list by for-statements.
return an iterator that must define the __next__ method.'''
itr = linkst()
itr.next = self.next
return itr #invariance: itr.data == itr
def __next__(self):
'''the for-statement depends on this method
to provide items one by one in the list.
return the next data, and move on.'''
#the invariance is checked so that a linked list
#will not be mistakenly iterated over
if self.data is not self or self.next is None:
raise StopIteration()
next = self.next
self.next = next.next
return next.data
def __repr__(self):
'''string representation of the list'''
return 'linkst(%r)'%list(self)
def __str__(self):
'''converting the list to a string'''
return '->'.join(str(i) for i in self)
#note: this is NOT the class lab! see file linked.py.
def extend(self, iterable):
'''takes an iterable, and append all items in the iterable
to the end of the list self.'''
last = self.data
for i in iterable:
last.next = linkst(None, i)
last = last.next
self.data = last
def index(self, data):
'''TODO: return first index of data in the list self.
Raises ValueError if the value is not present.'''
#must not convert self to a tuple or any other containers
current, idx = self.next, 0
while current:
if current.data == data: return idx
current, idx = current.next, idx+1
raise ValueError(data)
I think the implementation below fill the bill quite gracefully.
'''singly linked lists, by Yingjie Lan, December 1st, 2011'''
class linkst:
'''Singly linked list, with pythonic features.
The list has pointers to both the first and the last node.'''
__slots__ = ['data', 'next'] #memory efficient
def __init__(self, iterable=(), data=None, next=None):
'''Provide an iterable to make a singly linked list.
Set iterable to None to make a data node for internal use.'''
if iterable is not None:
self.data, self.next = self, None
self.extend(iterable)
else: #a common node
self.data, self.next = data, next
def empty(self):
'''test if the list is empty'''
return self.next is None
def append(self, data):
'''append to the end of list.'''
last = self.data
self.data = last.next = linkst(None, data)
#self.data = last.next
def insert(self, data, index=0):
'''insert data before index.
Raise IndexError if index is out of range'''
curr, cat = self, 0
while cat < index and curr:
curr, cat = curr.next, cat+1
if index<0 or not curr:
raise IndexError(index)
new = linkst(None, data, curr.next)
if curr.next is None: self.data = new
curr.next = new
def reverse(self):
'''reverse the order of list in place'''
current, prev = self.next, None
while current: #what if list is empty?
next = current.next
current.next = prev
prev, current = current, next
if self.next: self.data = self.next
self.next = prev
def delete(self, index=0):
'''remvoe the item at index from the list'''
curr, cat = self, 0
while cat < index and curr.next:
curr, cat = curr.next, cat+1
if index<0 or not curr.next:
raise IndexError(index)
curr.next = curr.next.next
if curr.next is None: #tail
self.data = curr #current == self?
def remove(self, data):
'''remove first occurrence of data.
Raises ValueError if the data is not present.'''
current = self
while current.next: #node to be examined
if data == current.next.data: break
current = current.next #move on
else: raise ValueError(data)
current.next = current.next.next
if current.next is None: #tail
self.data = current #current == self?
def __contains__(self, data):
'''membership test using keyword 'in'.'''
current = self.next
while current:
if data == current.data:
return True
current = current.next
return False
def __iter__(self):
'''iterate through list by for-statements.
return an iterator that must define the __next__ method.'''
itr = linkst()
itr.next = self.next
return itr #invariance: itr.data == itr
def __next__(self):
'''the for-statement depends on this method
to provide items one by one in the list.
return the next data, and move on.'''
#the invariance is checked so that a linked list
#will not be mistakenly iterated over
if self.data is not self or self.next is None:
raise StopIteration()
next = self.next
self.next = next.next
return next.data
def __repr__(self):
'''string representation of the list'''
return 'linkst(%r)'%list(self)
def __str__(self):
'''converting the list to a string'''
return '->'.join(str(i) for i in self)
#note: this is NOT the class lab! see file linked.py.
def extend(self, iterable):
'''takes an iterable, and append all items in the iterable
to the end of the list self.'''
last = self.data
for i in iterable:
last.next = linkst(None, i)
last = last.next
self.data = last
def index(self, data):
'''TODO: return first index of data in the list self.
Raises ValueError if the value is not present.'''
#must not convert self to a tuple or any other containers
current, idx = self.next, 0
while current:
if current.data == data: return idx
current, idx = current.next, idx+1
raise ValueError(data)
回答 19
class LinkedList:
def __init__(self, value):
self.value = value
self.next = None
def insert(self, node):
if not self.next:
self.next = node
else:
self.next.insert(node)
def __str__(self):
if self.next:
return '%s -> %s' % (self.value, str(self.next))
else:
return ' %s ' % self.value
if __name__ == "__main__":
items = ['a', 'b', 'c', 'd', 'e']
ll = None
for item in items:
if ll:
next_ll = LinkedList(item)
ll.insert(next_ll)
else:
ll = LinkedList(item)
print('[ %s ]' % ll)
class LinkedList:
def __init__(self, value):
self.value = value
self.next = None
def insert(self, node):
if not self.next:
self.next = node
else:
self.next.insert(node)
def __str__(self):
if self.next:
return '%s -> %s' % (self.value, str(self.next))
else:
return ' %s ' % self.value
if __name__ == "__main__":
items = ['a', 'b', 'c', 'd', 'e']
ll = None
for item in items:
if ll:
next_ll = LinkedList(item)
ll.insert(next_ll)
else:
ll = LinkedList(item)
print('[ %s ]' % ll)
回答 20
首先,我假设您要链接列表。实际上,您可以使用collections.deque
,其当前CPython实现是一个双链块列表(每个块包含62个货物对象的数组)。它包含了链表的功能。您也可以搜索llist
pypi上的C扩展名。如果您想要链表ADT的纯Python且易于遵循的实现,则可以看一下我的以下最小实现。
class Node (object):
""" Node for a linked list. """
def __init__ (self, value, next=None):
self.value = value
self.next = next
class LinkedList (object):
""" Linked list ADT implementation using class.
A linked list is a wrapper of a head pointer
that references either None, or a node that contains
a reference to a linked list.
"""
def __init__ (self, iterable=()):
self.head = None
for x in iterable:
self.head = Node(x, self.head)
def __iter__ (self):
p = self.head
while p is not None:
yield p.value
p = p.next
def prepend (self, x): # 'appendleft'
self.head = Node(x, self.head)
def reverse (self):
""" In-place reversal. """
p = self.head
self.head = None
while p is not None:
p0, p = p, p.next
p0.next = self.head
self.head = p0
if __name__ == '__main__':
ll = LinkedList([6,5,4])
ll.prepend(3); ll.prepend(2)
print list(ll)
ll.reverse()
print list(ll)
First of all, I assume you want linked lists. In practice, you can use collections.deque
, whose current CPython implementation is a doubly linked list of blocks (each block contains an array of 62 cargo objects). It subsumes linked list’s functionality. You can also search for a C extension called llist
on pypi. If you want a pure-Python and easy-to-follow implementation of the linked list ADT, you can take a look at my following minimal implementation.
class Node (object):
""" Node for a linked list. """
def __init__ (self, value, next=None):
self.value = value
self.next = next
class LinkedList (object):
""" Linked list ADT implementation using class.
A linked list is a wrapper of a head pointer
that references either None, or a node that contains
a reference to a linked list.
"""
def __init__ (self, iterable=()):
self.head = None
for x in iterable:
self.head = Node(x, self.head)
def __iter__ (self):
p = self.head
while p is not None:
yield p.value
p = p.next
def prepend (self, x): # 'appendleft'
self.head = Node(x, self.head)
def reverse (self):
""" In-place reversal. """
p = self.head
self.head = None
while p is not None:
p0, p = p, p.next
p0.next = self.head
self.head = p0
if __name__ == '__main__':
ll = LinkedList([6,5,4])
ll.prepend(3); ll.prepend(2)
print list(ll)
ll.reverse()
print list(ll)
回答 21
双向链表的示例(另存为linkedlist.py):
class node:
def __init__(self, before=None, cargo=None, next=None):
self._previous = before
self._cargo = cargo
self._next = next
def __str__(self):
return str(self._cargo) or None
class linkedList:
def __init__(self):
self._head = None
self._length = 0
def add(self, cargo):
n = node(None, cargo, self._head)
if self._head:
self._head._previous = n
self._head = n
self._length += 1
def search(self,cargo):
node = self._head
while (node and node._cargo != cargo):
node = node._next
return node
def delete(self,cargo):
node = self.search(cargo)
if node:
prev = node._previous
nx = node._next
if prev:
prev._next = node._next
else:
self._head = nx
nx._previous = None
if nx:
nx._previous = prev
else:
prev._next = None
self._length -= 1
def __str__(self):
print 'Size of linked list: ',self._length
node = self._head
while node:
print node
node = node._next
测试(另存为test.py):
from linkedlist import node, linkedList
def test():
print 'Testing Linked List'
l = linkedList()
l.add(10)
l.add(20)
l.add(30)
l.add(40)
l.add(50)
l.add(60)
print 'Linked List after insert nodes:'
l.__str__()
print 'Search some value, 30:'
node = l.search(30)
print node
print 'Delete some value, 30:'
node = l.delete(30)
l.__str__()
print 'Delete first element, 60:'
node = l.delete(60)
l.__str__()
print 'Delete last element, 10:'
node = l.delete(10)
l.__str__()
if __name__ == "__main__":
test()
输出:
Testing Linked List
Linked List after insert nodes:
Size of linked list: 6
60
50
40
30
20
10
Search some value, 30:
30
Delete some value, 30:
Size of linked list: 5
60
50
40
20
10
Delete first element, 60:
Size of linked list: 4
50
40
20
10
Delete last element, 10:
Size of linked list: 3
50
40
20
Sample of a doubly linked list (save as linkedlist.py):
class node:
def __init__(self, before=None, cargo=None, next=None):
self._previous = before
self._cargo = cargo
self._next = next
def __str__(self):
return str(self._cargo) or None
class linkedList:
def __init__(self):
self._head = None
self._length = 0
def add(self, cargo):
n = node(None, cargo, self._head)
if self._head:
self._head._previous = n
self._head = n
self._length += 1
def search(self,cargo):
node = self._head
while (node and node._cargo != cargo):
node = node._next
return node
def delete(self,cargo):
node = self.search(cargo)
if node:
prev = node._previous
nx = node._next
if prev:
prev._next = node._next
else:
self._head = nx
nx._previous = None
if nx:
nx._previous = prev
else:
prev._next = None
self._length -= 1
def __str__(self):
print 'Size of linked list: ',self._length
node = self._head
while node:
print node
node = node._next
Testing (save as test.py):
from linkedlist import node, linkedList
def test():
print 'Testing Linked List'
l = linkedList()
l.add(10)
l.add(20)
l.add(30)
l.add(40)
l.add(50)
l.add(60)
print 'Linked List after insert nodes:'
l.__str__()
print 'Search some value, 30:'
node = l.search(30)
print node
print 'Delete some value, 30:'
node = l.delete(30)
l.__str__()
print 'Delete first element, 60:'
node = l.delete(60)
l.__str__()
print 'Delete last element, 10:'
node = l.delete(10)
l.__str__()
if __name__ == "__main__":
test()
Output:
Testing Linked List
Linked List after insert nodes:
Size of linked list: 6
60
50
40
30
20
10
Search some value, 30:
30
Delete some value, 30:
Size of linked list: 5
60
50
40
20
10
Delete first element, 60:
Size of linked list: 4
50
40
20
10
Delete last element, 10:
Size of linked list: 3
50
40
20
回答 22
我也确实基于某个教程编写了一个单一链接列表,它具有两个基本的Node和Linked List类,以及一些其他的插入,删除,反向,排序等方法。
这不是最好或最简单的方法,但是可以。
"""
🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏
Single Linked List (SLL):
A simple object-oriented implementation of Single Linked List (SLL)
with some associated methods, such as create list, count nodes, delete nodes, and such.
🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏
"""
class Node:
"""
Instantiates a node
"""
def __init__(self, value):
"""
Node class constructor which sets the value and link of the node
"""
self.info = value
self.link = None
class SingleLinkedList:
"""
Instantiates the SLL class
"""
def __init__(self):
"""
SLL class constructor which sets the value and link of the node
"""
self.start = None
def create_single_linked_list(self):
"""
Reads values from stdin and appends them to this list and creates a SLL with integer nodes
"""
try:
number_of_nodes = int(input("👉 Enter a positive integer between 1-50 for the number of nodes you wish to have in the list: "))
if number_of_nodes <= 0 or number_of_nodes > 51:
print("💛 The number of nodes though must be an integer between 1 to 50!")
self.create_single_linked_list()
except Exception as e:
print("💛 Error: ", e)
self.create_single_linked_list()
try:
for _ in range(number_of_nodes):
try:
data = int(input("👉 Enter an integer for the node to be inserted: "))
self.insert_node_at_end(data)
except Exception as e:
print("💛 Error: ", e)
except Exception as e:
print("💛 Error: ", e)
def count_sll_nodes(self):
"""
Counts the nodes of the linked list
"""
try:
p = self.start
n = 0
while p is not None:
n += 1
p = p.link
if n >= 1:
print(f"💚 The number of nodes in the linked list is {n}")
else:
print(f"💛 The SLL does not have a node!")
except Exception as e:
print("💛 Error: ", e)
def search_sll_nodes(self, x):
"""
Searches the x integer in the linked list
"""
try:
position = 1
p = self.start
while p is not None:
if p.info == x:
print(f"💚 YAAAY! We found {x} at position {position}")
return True
#Increment the position
position += 1
#Assign the next node to the current node
p = p.link
else:
print(f"💔 Sorry! We couldn't find {x} at any position. Maybe, you might want to use option 9 and try again later!")
return False
except Exception as e:
print("💛 Error: ", e)
def display_sll(self):
"""
Displays the list
"""
try:
if self.start is None:
print("💛 Single linked list is empty!")
return
display_sll = "💚 Single linked list nodes are: "
p = self.start
while p is not None:
display_sll += str(p.info) + "\t"
p = p.link
print(display_sll)
except Exception as e:
print("💛 Error: ", e)
def insert_node_in_beginning(self, data):
"""
Inserts an integer in the beginning of the linked list
"""
try:
temp = Node(data)
temp.link = self.start
self.start = temp
except Exception as e:
print("💛 Error: ", e)
def insert_node_at_end(self, data):
"""
Inserts an integer at the end of the linked list
"""
try:
temp = Node(data)
if self.start is None:
self.start = temp
return
p = self.start
while p.link is not None:
p = p.link
p.link = temp
except Exception as e:
print("💛 Error: ", e)
def insert_node_after_another(self, data, x):
"""
Inserts an integer after the x node
"""
try:
p = self.start
while p is not None:
if p.info == x:
break
p = p.link
if p is None:
print(f"💔 Sorry! {x} is not in the list.")
else:
temp = Node(data)
temp.link = p.link
p.link = temp
except Exception as e:
print("💛 Error: ", e)
def insert_node_before_another(self, data, x):
"""
Inserts an integer before the x node
"""
try:
# If list is empty
if self.start is None:
print("💔 Sorry! The list is empty.")
return
# If x is the first node, and new node should be inserted before the first node
if x == self.start.info:
temp = Node(data)
temp.link = p.link
p.link = temp
# Finding the reference to the prior node containing x
p = self.start
while p.link is not None:
if p.link.info == x:
break
p = p.link
if p.link is not None:
print(f"💔 Sorry! {x} is not in the list.")
else:
temp = Node(data)
temp.link = p.link
p.link = temp
except Exception as e:
print("💛 Error: ", e)
def insert_node_at_position(self, data, k):
"""
Inserts an integer in k position of the linked list
"""
try:
# if we wish to insert at the first node
if k == 1:
temp = Node(data)
temp.link = self.start
self.start = temp
return
p = self.start
i = 1
while i < k-1 and p is not None:
p = p.link
i += 1
if p is None:
print(f"💛 The max position is {i}")
else:
temp = Node(data)
temp.link = self.start
self.start = temp
except Exception as e:
print("💛 Error: ", e)
def delete_a_node(self, x):
"""
Deletes a node of a linked list
"""
try:
# If list is empty
if self.start is None:
print("💔 Sorry! The list is empty.")
return
# If there is only one node
if self.start.info == x:
self.start = self.start.link
# If more than one node exists
p = self.start
while p.link is not None:
if p.link.info == x:
break
p = p.link
if p.link is None:
print(f"💔 Sorry! {x} is not in the list.")
else:
p.link = p.link.link
except Exception as e:
print("💛 Error: ", e)
def delete_sll_first_node(self):
"""
Deletes the first node of a linked list
"""
try:
if self.start is None:
return
self.start = self.start.link
except Exception as e:
print("💛 Error: ", e)
def delete_sll_last_node(self):
"""
Deletes the last node of a linked list
"""
try:
# If the list is empty
if self.start is None:
return
# If there is only one node
if self.start.link is None:
self.start = None
return
# If there is more than one node
p = self.start
# Increment until we find the node prior to the last node
while p.link.link is not None:
p = p.link
p.link = None
except Exception as e:
print("💛 Error: ", e)
def reverse_sll(self):
"""
Reverses the linked list
"""
try:
prev = None
p = self.start
while p is not None:
next = p.link
p.link = prev
prev = p
p = next
self.start = prev
except Exception as e:
print("💛 Error: ", e)
def bubble_sort_sll_nodes_data(self):
"""
Bubble sorts the linked list on integer values
"""
try:
# If the list is empty or there is only one node
if self.start is None or self.start.link is None:
print("💛 The list has no or only one node and sorting is not required.")
end = None
while end != self.start.link:
p = self.start
while p.link != end:
q = p.link
if p.info > q.info:
p.info, q.info = q.info, p.info
p = p.link
end = p
except Exception as e:
print("💛 Error: ", e)
def bubble_sort_sll(self):
"""
Bubble sorts the linked list
"""
try:
# If the list is empty or there is only one node
if self.start is None or self.start.link is None:
print("💛 The list has no or only one node and sorting is not required.")
end = None
while end != self.start.link:
r = p = self.start
while p.link != end:
q = p.link
if p.info > q.info:
p.link = q.link
q.link = p
if p != self.start:
r.link = q.link
else:
self.start = q
p, q = q, p
r = p
p = p.link
end = p
except Exception as e:
print("💛 Error: ", e)
def sll_has_cycle(self):
"""
Tests the list for cycles using Tortoise and Hare Algorithm (Floyd's cycle detection algorithm)
"""
try:
if self.find_sll_cycle() is None:
return False
else:
return True
except Exception as e:
print("💛 Error: ", e)
def find_sll_cycle(self):
"""
Finds cycles in the list, if any
"""
try:
# If there is one node or none, there is no cycle
if self.start is None or self.start.link is None:
return None
# Otherwise,
slowR = self.start
fastR = self.start
while slowR is not None and fastR is not None:
slowR = slowR.link
fastR = fastR.link.link
if slowR == fastR:
return slowR
return None
except Exception as e:
print("💛 Error: ", e)
def remove_cycle_from_sll(self):
"""
Removes the cycles
"""
try:
c = self.find_sll_cycle()
# If there is no cycle
if c is None:
return
print(f"💛 There is a cycle at node: ", c.info)
p = c
q = c
len_cycles = 0
while True:
len_cycles += 1
q = q.link
if p == q:
break
print(f"💛 The cycle length is {len_cycles}")
len_rem_list = 0
p = self.start
while p != q:
len_rem_list += 1
p = p.link
q = q.link
print(f"💛 The number of nodes not included in the cycle is {len_rem_list}")
length_list = len_rem_list + len_cycles
print(f"💛 The SLL length is {length_list}")
# This for loop goes to the end of the SLL, and set the last node to None and the cycle is removed.
p = self.start
for _ in range(length_list-1):
p = p.link
p.link = None
except Exception as e:
print("💛 Error: ", e)
def insert_cycle_in_sll(self, x):
"""
Inserts a cycle at a node that contains x
"""
try:
if self.start is None:
return False
p = self.start
px = None
prev = None
while p is not None:
if p.info == x:
px = p
prev = p
p = p.link
if px is not None:
prev.link = px
else:
print(f"💔 Sorry! {x} is not in the list.")
except Exception as e:
print("💛 Error: ", e)
def merge_using_new_list(self, list2):
"""
Merges two already sorted SLLs by creating new lists
"""
merge_list = SingleLinkedList()
merge_list.start = self._merge_using_new_list(self.start, list2.start)
return merge_list
def _merge_using_new_list(self, p1, p2):
"""
Private method of merge_using_new_list
"""
if p1.info <= p2.info:
Start_merge = Node(p1.info)
p1 = p1.link
else:
Start_merge = Node(p2.info)
p2 = p2.link
pM = Start_merge
while p1 is not None and p2 is not None:
if p1.info <= p2.info:
pM.link = Node(p1.info)
p1 = p1.link
else:
pM.link = Node(p2.info)
p2 = p2.link
pM = pM.link
#If the second list is finished, yet the first list has some nodes
while p1 is not None:
pM.link = Node(p1.info)
p1 = p1.link
pM = pM.link
#If the second list is finished, yet the first list has some nodes
while p2 is not None:
pM.link = Node(p2.info)
p2 = p2.link
pM = pM.link
return Start_merge
def merge_inplace(self, list2):
"""
Merges two already sorted SLLs in place in O(1) of space
"""
merge_list = SingleLinkedList()
merge_list.start = self._merge_inplace(self.start, list2.start)
return merge_list
def _merge_inplace(self, p1, p2):
"""
Merges two already sorted SLLs in place in O(1) of space
"""
if p1.info <= p2.info:
Start_merge = p1
p1 = p1.link
else:
Start_merge = p2
p2 = p2.link
pM = Start_merge
while p1 is not None and p2 is not None:
if p1.info <= p2.info:
pM.link = p1
pM = pM.link
p1 = p1.link
else:
pM.link = p2
pM = pM.link
p2 = p2.link
if p1 is None:
pM.link = p2
else:
pM.link = p1
return Start_merge
def merge_sort_sll(self):
"""
Sorts the linked list using merge sort algorithm
"""
self.start = self._merge_sort_recursive(self.start)
def _merge_sort_recursive(self, list_start):
"""
Recursively calls the merge sort algorithm for two divided lists
"""
# If the list is empty or has only one node
if list_start is None or list_start.link is None:
return list_start
# If the list has two nodes or more
start_one = list_start
start_two = self._divide_list(self_start)
start_one = self._merge_sort_recursive(start_one)
start_two = self._merge_sort_recursive(start_two)
start_merge = self._merge_inplace(start_one, start_two)
return start_merge
def _divide_list(self, p):
"""
Divides the linked list into two almost equally sized lists
"""
# Refers to the third nodes of the list
q = p.link.link
while q is not None and p is not None:
# Increments p one node at the time
p = p.link
# Increments q two nodes at the time
q = q.link.link
start_two = p.link
p.link = None
return start_two
def concat_second_list_to_sll(self, list2):
"""
Concatenates another SLL to an existing SLL
"""
# If the second SLL has no node
if list2.start is None:
return
# If the original SLL has no node
if self.start is None:
self.start = list2.start
return
# Otherwise traverse the original SLL
p = self.start
while p.link is not None:
p = p.link
# Link the last node to the first node of the second SLL
p.link = list2.start
def test_merge_using_new_list_and_inplace(self):
"""
"""
LIST_ONE = SingleLinkedList()
LIST_TWO = SingleLinkedList()
LIST_ONE.create_single_linked_list()
LIST_TWO.create_single_linked_list()
print("1️⃣ The unsorted first list is: ")
LIST_ONE.display_sll()
print("2️⃣ The unsorted second list is: ")
LIST_TWO.display_sll()
LIST_ONE.bubble_sort_sll_nodes_data()
LIST_TWO.bubble_sort_sll_nodes_data()
print("1️⃣ The sorted first list is: ")
LIST_ONE.display_sll()
print("2️⃣ The sorted second list is: ")
LIST_TWO.display_sll()
LIST_THREE = LIST_ONE.merge_using_new_list(LIST_TWO)
print("The merged list by creating a new list is: ")
LIST_THREE.display_sll()
LIST_FOUR = LIST_ONE.merge_inplace(LIST_TWO)
print("The in-place merged list is: ")
LIST_FOUR.display_sll()
def test_all_methods(self):
"""
Tests all methods of the SLL class
"""
OPTIONS_HELP = """
📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗
Select a method from 1-19:
🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒
ℹ️ (1) 👉 Create a single liked list (SLL).
ℹ️ (2) 👉 Display the SLL.
ℹ️ (3) 👉 Count the nodes of SLL.
ℹ️ (4) 👉 Search the SLL.
ℹ️ (5) 👉 Insert a node at the beginning of the SLL.
ℹ️ (6) 👉 Insert a node at the end of the SLL.
ℹ️ (7) 👉 Insert a node after a specified node of the SLL.
ℹ️ (8) 👉 Insert a node before a specified node of the SLL.
ℹ️ (9) 👉 Delete the first node of SLL.
ℹ️ (10) 👉 Delete the last node of the SLL.
ℹ️ (11) 👉 Delete a node you wish to remove.
ℹ️ (12) 👉 Reverse the SLL.
ℹ️ (13) 👉 Bubble sort the SLL by only exchanging the integer values.
ℹ️ (14) 👉 Bubble sort the SLL by exchanging links.
ℹ️ (15) 👉 Merge sort the SLL.
ℹ️ (16) 👉 Insert a cycle in the SLL.
ℹ️ (17) 👉 Detect if the SLL has a cycle.
ℹ️ (18) 👉 Remove cycle in the SLL.
ℹ️ (19) 👉 Test merging two bubble-sorted SLLs.
ℹ️ (20) 👉 Concatenate a second list to the SLL.
ℹ️ (21) 👉 Exit.
📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗
"""
self.create_single_linked_list()
while True:
print(OPTIONS_HELP)
UI_OPTION = int(input("👉 Enter an integer for the method you wish to run using the above help: "))
if UI_OPTION == 1:
data = int(input("👉 Enter an integer to be inserted at the end of the list: "))
x = int(input("👉 Enter an integer to be inserted after that: "))
self.insert_node_after_another(data, x)
elif UI_OPTION == 2:
self.display_sll()
elif UI_OPTION == 3:
self.count_sll_nodes()
elif UI_OPTION == 4:
data = int(input("👉 Enter an integer to be searched: "))
self.search_sll_nodes(data)
elif UI_OPTION == 5:
data = int(input("👉 Enter an integer to be inserted at the beginning: "))
self.insert_node_in_beginning(data)
elif UI_OPTION == 6:
data = int(input("👉 Enter an integer to be inserted at the end: "))
self.insert_node_at_end(data)
elif UI_OPTION == 7:
data = int(input("👉 Enter an integer to be inserted: "))
x = int(input("👉 Enter an integer to be inserted before that: "))
self.insert_node_before_another(data, x)
elif UI_OPTION == 8:
data = int(input("👉 Enter an integer for the node to be inserted: "))
k = int(input("👉 Enter an integer for the position at which you wish to insert the node: "))
self.insert_node_before_another(data, k)
elif UI_OPTION == 9:
self.delete_sll_first_node()
elif UI_OPTION == 10:
self.delete_sll_last_node()
elif UI_OPTION == 11:
data = int(input("👉 Enter an integer for the node you wish to remove: "))
self.delete_a_node(data)
elif UI_OPTION == 12:
self.reverse_sll()
elif UI_OPTION == 13:
self.bubble_sort_sll_nodes_data()
elif UI_OPTION == 14:
self.bubble_sort_sll()
elif UI_OPTION == 15:
self.merge_sort_sll()
elif UI_OPTION == 16:
data = int(input("👉 Enter an integer at which a cycle has to be formed: "))
self.insert_cycle_in_sll(data)
elif UI_OPTION == 17:
if self.sll_has_cycle():
print("💛 The linked list has a cycle. ")
else:
print("💚 YAAAY! The linked list does not have a cycle. ")
elif UI_OPTION == 18:
self.remove_cycle_from_sll()
elif UI_OPTION == 19:
self.test_merge_using_new_list_and_inplace()
elif UI_OPTION == 20:
list2 = self.create_single_linked_list()
self.concat_second_list_to_sll(list2)
elif UI_OPTION == 21:
break
else:
print("💛 Option must be an integer, between 1 to 21.")
print()
if __name__ == '__main__':
# Instantiates a new SLL object
SLL_OBJECT = SingleLinkedList()
SLL_OBJECT.test_all_methods()
I did also write a Single Linked List based on some tutorial, which has the basic two Node and Linked List classes, and some additional methods for insertion, delete, reverse, sorting, and such.
It’s not the best or easiest, works OK though.
"""
🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏
Single Linked List (SLL):
A simple object-oriented implementation of Single Linked List (SLL)
with some associated methods, such as create list, count nodes, delete nodes, and such.
🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎🍏
"""
class Node:
"""
Instantiates a node
"""
def __init__(self, value):
"""
Node class constructor which sets the value and link of the node
"""
self.info = value
self.link = None
class SingleLinkedList:
"""
Instantiates the SLL class
"""
def __init__(self):
"""
SLL class constructor which sets the value and link of the node
"""
self.start = None
def create_single_linked_list(self):
"""
Reads values from stdin and appends them to this list and creates a SLL with integer nodes
"""
try:
number_of_nodes = int(input("👉 Enter a positive integer between 1-50 for the number of nodes you wish to have in the list: "))
if number_of_nodes <= 0 or number_of_nodes > 51:
print("💛 The number of nodes though must be an integer between 1 to 50!")
self.create_single_linked_list()
except Exception as e:
print("💛 Error: ", e)
self.create_single_linked_list()
try:
for _ in range(number_of_nodes):
try:
data = int(input("👉 Enter an integer for the node to be inserted: "))
self.insert_node_at_end(data)
except Exception as e:
print("💛 Error: ", e)
except Exception as e:
print("💛 Error: ", e)
def count_sll_nodes(self):
"""
Counts the nodes of the linked list
"""
try:
p = self.start
n = 0
while p is not None:
n += 1
p = p.link
if n >= 1:
print(f"💚 The number of nodes in the linked list is {n}")
else:
print(f"💛 The SLL does not have a node!")
except Exception as e:
print("💛 Error: ", e)
def search_sll_nodes(self, x):
"""
Searches the x integer in the linked list
"""
try:
position = 1
p = self.start
while p is not None:
if p.info == x:
print(f"💚 YAAAY! We found {x} at position {position}")
return True
#Increment the position
position += 1
#Assign the next node to the current node
p = p.link
else:
print(f"💔 Sorry! We couldn't find {x} at any position. Maybe, you might want to use option 9 and try again later!")
return False
except Exception as e:
print("💛 Error: ", e)
def display_sll(self):
"""
Displays the list
"""
try:
if self.start is None:
print("💛 Single linked list is empty!")
return
display_sll = "💚 Single linked list nodes are: "
p = self.start
while p is not None:
display_sll += str(p.info) + "\t"
p = p.link
print(display_sll)
except Exception as e:
print("💛 Error: ", e)
def insert_node_in_beginning(self, data):
"""
Inserts an integer in the beginning of the linked list
"""
try:
temp = Node(data)
temp.link = self.start
self.start = temp
except Exception as e:
print("💛 Error: ", e)
def insert_node_at_end(self, data):
"""
Inserts an integer at the end of the linked list
"""
try:
temp = Node(data)
if self.start is None:
self.start = temp
return
p = self.start
while p.link is not None:
p = p.link
p.link = temp
except Exception as e:
print("💛 Error: ", e)
def insert_node_after_another(self, data, x):
"""
Inserts an integer after the x node
"""
try:
p = self.start
while p is not None:
if p.info == x:
break
p = p.link
if p is None:
print(f"💔 Sorry! {x} is not in the list.")
else:
temp = Node(data)
temp.link = p.link
p.link = temp
except Exception as e:
print("💛 Error: ", e)
def insert_node_before_another(self, data, x):
"""
Inserts an integer before the x node
"""
try:
# If list is empty
if self.start is None:
print("💔 Sorry! The list is empty.")
return
# If x is the first node, and new node should be inserted before the first node
if x == self.start.info:
temp = Node(data)
temp.link = p.link
p.link = temp
# Finding the reference to the prior node containing x
p = self.start
while p.link is not None:
if p.link.info == x:
break
p = p.link
if p.link is not None:
print(f"💔 Sorry! {x} is not in the list.")
else:
temp = Node(data)
temp.link = p.link
p.link = temp
except Exception as e:
print("💛 Error: ", e)
def insert_node_at_position(self, data, k):
"""
Inserts an integer in k position of the linked list
"""
try:
# if we wish to insert at the first node
if k == 1:
temp = Node(data)
temp.link = self.start
self.start = temp
return
p = self.start
i = 1
while i < k-1 and p is not None:
p = p.link
i += 1
if p is None:
print(f"💛 The max position is {i}")
else:
temp = Node(data)
temp.link = self.start
self.start = temp
except Exception as e:
print("💛 Error: ", e)
def delete_a_node(self, x):
"""
Deletes a node of a linked list
"""
try:
# If list is empty
if self.start is None:
print("💔 Sorry! The list is empty.")
return
# If there is only one node
if self.start.info == x:
self.start = self.start.link
# If more than one node exists
p = self.start
while p.link is not None:
if p.link.info == x:
break
p = p.link
if p.link is None:
print(f"💔 Sorry! {x} is not in the list.")
else:
p.link = p.link.link
except Exception as e:
print("💛 Error: ", e)
def delete_sll_first_node(self):
"""
Deletes the first node of a linked list
"""
try:
if self.start is None:
return
self.start = self.start.link
except Exception as e:
print("💛 Error: ", e)
def delete_sll_last_node(self):
"""
Deletes the last node of a linked list
"""
try:
# If the list is empty
if self.start is None:
return
# If there is only one node
if self.start.link is None:
self.start = None
return
# If there is more than one node
p = self.start
# Increment until we find the node prior to the last node
while p.link.link is not None:
p = p.link
p.link = None
except Exception as e:
print("💛 Error: ", e)
def reverse_sll(self):
"""
Reverses the linked list
"""
try:
prev = None
p = self.start
while p is not None:
next = p.link
p.link = prev
prev = p
p = next
self.start = prev
except Exception as e:
print("💛 Error: ", e)
def bubble_sort_sll_nodes_data(self):
"""
Bubble sorts the linked list on integer values
"""
try:
# If the list is empty or there is only one node
if self.start is None or self.start.link is None:
print("💛 The list has no or only one node and sorting is not required.")
end = None
while end != self.start.link:
p = self.start
while p.link != end:
q = p.link
if p.info > q.info:
p.info, q.info = q.info, p.info
p = p.link
end = p
except Exception as e:
print("💛 Error: ", e)
def bubble_sort_sll(self):
"""
Bubble sorts the linked list
"""
try:
# If the list is empty or there is only one node
if self.start is None or self.start.link is None:
print("💛 The list has no or only one node and sorting is not required.")
end = None
while end != self.start.link:
r = p = self.start
while p.link != end:
q = p.link
if p.info > q.info:
p.link = q.link
q.link = p
if p != self.start:
r.link = q.link
else:
self.start = q
p, q = q, p
r = p
p = p.link
end = p
except Exception as e:
print("💛 Error: ", e)
def sll_has_cycle(self):
"""
Tests the list for cycles using Tortoise and Hare Algorithm (Floyd's cycle detection algorithm)
"""
try:
if self.find_sll_cycle() is None:
return False
else:
return True
except Exception as e:
print("💛 Error: ", e)
def find_sll_cycle(self):
"""
Finds cycles in the list, if any
"""
try:
# If there is one node or none, there is no cycle
if self.start is None or self.start.link is None:
return None
# Otherwise,
slowR = self.start
fastR = self.start
while slowR is not None and fastR is not None:
slowR = slowR.link
fastR = fastR.link.link
if slowR == fastR:
return slowR
return None
except Exception as e:
print("💛 Error: ", e)
def remove_cycle_from_sll(self):
"""
Removes the cycles
"""
try:
c = self.find_sll_cycle()
# If there is no cycle
if c is None:
return
print(f"💛 There is a cycle at node: ", c.info)
p = c
q = c
len_cycles = 0
while True:
len_cycles += 1
q = q.link
if p == q:
break
print(f"💛 The cycle length is {len_cycles}")
len_rem_list = 0
p = self.start
while p != q:
len_rem_list += 1
p = p.link
q = q.link
print(f"💛 The number of nodes not included in the cycle is {len_rem_list}")
length_list = len_rem_list + len_cycles
print(f"💛 The SLL length is {length_list}")
# This for loop goes to the end of the SLL, and set the last node to None and the cycle is removed.
p = self.start
for _ in range(length_list-1):
p = p.link
p.link = None
except Exception as e:
print("💛 Error: ", e)
def insert_cycle_in_sll(self, x):
"""
Inserts a cycle at a node that contains x
"""
try:
if self.start is None:
return False
p = self.start
px = None
prev = None
while p is not None:
if p.info == x:
px = p
prev = p
p = p.link
if px is not None:
prev.link = px
else:
print(f"💔 Sorry! {x} is not in the list.")
except Exception as e:
print("💛 Error: ", e)
def merge_using_new_list(self, list2):
"""
Merges two already sorted SLLs by creating new lists
"""
merge_list = SingleLinkedList()
merge_list.start = self._merge_using_new_list(self.start, list2.start)
return merge_list
def _merge_using_new_list(self, p1, p2):
"""
Private method of merge_using_new_list
"""
if p1.info <= p2.info:
Start_merge = Node(p1.info)
p1 = p1.link
else:
Start_merge = Node(p2.info)
p2 = p2.link
pM = Start_merge
while p1 is not None and p2 is not None:
if p1.info <= p2.info:
pM.link = Node(p1.info)
p1 = p1.link
else:
pM.link = Node(p2.info)
p2 = p2.link
pM = pM.link
#If the second list is finished, yet the first list has some nodes
while p1 is not None:
pM.link = Node(p1.info)
p1 = p1.link
pM = pM.link
#If the second list is finished, yet the first list has some nodes
while p2 is not None:
pM.link = Node(p2.info)
p2 = p2.link
pM = pM.link
return Start_merge
def merge_inplace(self, list2):
"""
Merges two already sorted SLLs in place in O(1) of space
"""
merge_list = SingleLinkedList()
merge_list.start = self._merge_inplace(self.start, list2.start)
return merge_list
def _merge_inplace(self, p1, p2):
"""
Merges two already sorted SLLs in place in O(1) of space
"""
if p1.info <= p2.info:
Start_merge = p1
p1 = p1.link
else:
Start_merge = p2
p2 = p2.link
pM = Start_merge
while p1 is not None and p2 is not None:
if p1.info <= p2.info:
pM.link = p1
pM = pM.link
p1 = p1.link
else:
pM.link = p2
pM = pM.link
p2 = p2.link
if p1 is None:
pM.link = p2
else:
pM.link = p1
return Start_merge
def merge_sort_sll(self):
"""
Sorts the linked list using merge sort algorithm
"""
self.start = self._merge_sort_recursive(self.start)
def _merge_sort_recursive(self, list_start):
"""
Recursively calls the merge sort algorithm for two divided lists
"""
# If the list is empty or has only one node
if list_start is None or list_start.link is None:
return list_start
# If the list has two nodes or more
start_one = list_start
start_two = self._divide_list(self_start)
start_one = self._merge_sort_recursive(start_one)
start_two = self._merge_sort_recursive(start_two)
start_merge = self._merge_inplace(start_one, start_two)
return start_merge
def _divide_list(self, p):
"""
Divides the linked list into two almost equally sized lists
"""
# Refers to the third nodes of the list
q = p.link.link
while q is not None and p is not None:
# Increments p one node at the time
p = p.link
# Increments q two nodes at the time
q = q.link.link
start_two = p.link
p.link = None
return start_two
def concat_second_list_to_sll(self, list2):
"""
Concatenates another SLL to an existing SLL
"""
# If the second SLL has no node
if list2.start is None:
return
# If the original SLL has no node
if self.start is None:
self.start = list2.start
return
# Otherwise traverse the original SLL
p = self.start
while p.link is not None:
p = p.link
# Link the last node to the first node of the second SLL
p.link = list2.start
def test_merge_using_new_list_and_inplace(self):
"""
"""
LIST_ONE = SingleLinkedList()
LIST_TWO = SingleLinkedList()
LIST_ONE.create_single_linked_list()
LIST_TWO.create_single_linked_list()
print("1️⃣ The unsorted first list is: ")
LIST_ONE.display_sll()
print("2️⃣ The unsorted second list is: ")
LIST_TWO.display_sll()
LIST_ONE.bubble_sort_sll_nodes_data()
LIST_TWO.bubble_sort_sll_nodes_data()
print("1️⃣ The sorted first list is: ")
LIST_ONE.display_sll()
print("2️⃣ The sorted second list is: ")
LIST_TWO.display_sll()
LIST_THREE = LIST_ONE.merge_using_new_list(LIST_TWO)
print("The merged list by creating a new list is: ")
LIST_THREE.display_sll()
LIST_FOUR = LIST_ONE.merge_inplace(LIST_TWO)
print("The in-place merged list is: ")
LIST_FOUR.display_sll()
def test_all_methods(self):
"""
Tests all methods of the SLL class
"""
OPTIONS_HELP = """
📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗
Select a method from 1-19:
🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒
ℹ️ (1) 👉 Create a single liked list (SLL).
ℹ️ (2) 👉 Display the SLL.
ℹ️ (3) 👉 Count the nodes of SLL.
ℹ️ (4) 👉 Search the SLL.
ℹ️ (5) 👉 Insert a node at the beginning of the SLL.
ℹ️ (6) 👉 Insert a node at the end of the SLL.
ℹ️ (7) 👉 Insert a node after a specified node of the SLL.
ℹ️ (8) 👉 Insert a node before a specified node of the SLL.
ℹ️ (9) 👉 Delete the first node of SLL.
ℹ️ (10) 👉 Delete the last node of the SLL.
ℹ️ (11) 👉 Delete a node you wish to remove.
ℹ️ (12) 👉 Reverse the SLL.
ℹ️ (13) 👉 Bubble sort the SLL by only exchanging the integer values.
ℹ️ (14) 👉 Bubble sort the SLL by exchanging links.
ℹ️ (15) 👉 Merge sort the SLL.
ℹ️ (16) 👉 Insert a cycle in the SLL.
ℹ️ (17) 👉 Detect if the SLL has a cycle.
ℹ️ (18) 👉 Remove cycle in the SLL.
ℹ️ (19) 👉 Test merging two bubble-sorted SLLs.
ℹ️ (20) 👉 Concatenate a second list to the SLL.
ℹ️ (21) 👉 Exit.
📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗📗
"""
self.create_single_linked_list()
while True:
print(OPTIONS_HELP)
UI_OPTION = int(input("👉 Enter an integer for the method you wish to run using the above help: "))
if UI_OPTION == 1:
data = int(input("👉 Enter an integer to be inserted at the end of the list: "))
x = int(input("👉 Enter an integer to be inserted after that: "))
self.insert_node_after_another(data, x)
elif UI_OPTION == 2:
self.display_sll()
elif UI_OPTION == 3:
self.count_sll_nodes()
elif UI_OPTION == 4:
data = int(input("👉 Enter an integer to be searched: "))
self.search_sll_nodes(data)
elif UI_OPTION == 5:
data = int(input("👉 Enter an integer to be inserted at the beginning: "))
self.insert_node_in_beginning(data)
elif UI_OPTION == 6:
data = int(input("👉 Enter an integer to be inserted at the end: "))
self.insert_node_at_end(data)
elif UI_OPTION == 7:
data = int(input("👉 Enter an integer to be inserted: "))
x = int(input("👉 Enter an integer to be inserted before that: "))
self.insert_node_before_another(data, x)
elif UI_OPTION == 8:
data = int(input("👉 Enter an integer for the node to be inserted: "))
k = int(input("👉 Enter an integer for the position at which you wish to insert the node: "))
self.insert_node_before_another(data, k)
elif UI_OPTION == 9:
self.delete_sll_first_node()
elif UI_OPTION == 10:
self.delete_sll_last_node()
elif UI_OPTION == 11:
data = int(input("👉 Enter an integer for the node you wish to remove: "))
self.delete_a_node(data)
elif UI_OPTION == 12:
self.reverse_sll()
elif UI_OPTION == 13:
self.bubble_sort_sll_nodes_data()
elif UI_OPTION == 14:
self.bubble_sort_sll()
elif UI_OPTION == 15:
self.merge_sort_sll()
elif UI_OPTION == 16:
data = int(input("👉 Enter an integer at which a cycle has to be formed: "))
self.insert_cycle_in_sll(data)
elif UI_OPTION == 17:
if self.sll_has_cycle():
print("💛 The linked list has a cycle. ")
else:
print("💚 YAAAY! The linked list does not have a cycle. ")
elif UI_OPTION == 18:
self.remove_cycle_from_sll()
elif UI_OPTION == 19:
self.test_merge_using_new_list_and_inplace()
elif UI_OPTION == 20:
list2 = self.create_single_linked_list()
self.concat_second_list_to_sll(list2)
elif UI_OPTION == 21:
break
else:
print("💛 Option must be an integer, between 1 to 21.")
print()
if __name__ == '__main__':
# Instantiates a new SLL object
SLL_OBJECT = SingleLinkedList()
SLL_OBJECT.test_all_methods()
回答 23
扩展尼克·斯蒂纳姆斯的答案
class Node(object):
def __init__(self):
self.data = None
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def prepend_node(self, data):
new_node = Node()
new_node.data = data
new_node.next = self.head
self.head = new_node
def append_node(self, data):
new_node = Node()
new_node.data = data
current = self.head
while current.next:
current = current.next
current.next = new_node
def reverse(self):
""" In-place reversal, modifies exiting list"""
previous = None
current_node = self.head
while current_node:
temp = current_node.next
current_node.next = previous
previous = current_node
current_node = temp
self.head = previous
def search(self, data):
current_node = self.head
try:
while current_node.data != data:
current_node = current_node.next
return True
except:
return False
def display(self):
if self.head is None:
print("Linked list is empty")
else:
current_node = self.head
while current_node:
print(current_node.data)
current_node = current_node.next
def list_length(self):
list_length = 0
current_node = self.head
while current_node:
list_length += 1
current_node = current_node.next
return list_length
def main():
linked_list = LinkedList()
linked_list.prepend_node(1)
linked_list.prepend_node(2)
linked_list.prepend_node(3)
linked_list.append_node(24)
linked_list.append_node(25)
linked_list.display()
linked_list.reverse()
linked_list.display()
print(linked_list.search(1))
linked_list.reverse()
linked_list.display()
print("Lenght of singly linked list is: " + str(linked_list.list_length()))
if __name__ == "__main__":
main()
Expanding Nick Stinemates’s answer
class Node(object):
def __init__(self):
self.data = None
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def prepend_node(self, data):
new_node = Node()
new_node.data = data
new_node.next = self.head
self.head = new_node
def append_node(self, data):
new_node = Node()
new_node.data = data
current = self.head
while current.next:
current = current.next
current.next = new_node
def reverse(self):
""" In-place reversal, modifies exiting list"""
previous = None
current_node = self.head
while current_node:
temp = current_node.next
current_node.next = previous
previous = current_node
current_node = temp
self.head = previous
def search(self, data):
current_node = self.head
try:
while current_node.data != data:
current_node = current_node.next
return True
except:
return False
def display(self):
if self.head is None:
print("Linked list is empty")
else:
current_node = self.head
while current_node:
print(current_node.data)
current_node = current_node.next
def list_length(self):
list_length = 0
current_node = self.head
while current_node:
list_length += 1
current_node = current_node.next
return list_length
def main():
linked_list = LinkedList()
linked_list.prepend_node(1)
linked_list.prepend_node(2)
linked_list.prepend_node(3)
linked_list.append_node(24)
linked_list.append_node(25)
linked_list.display()
linked_list.reverse()
linked_list.display()
print(linked_list.search(1))
linked_list.reverse()
linked_list.display()
print("Lenght of singly linked list is: " + str(linked_list.list_length()))
if __name__ == "__main__":
main()
回答 24
我的2美分
class Node:
def __init__(self, value=None, next=None):
self.value = value
self.next = next
def __str__(self):
return str(self.value)
class LinkedList:
def __init__(self):
self.first = None
self.last = None
def add(self, x):
current = Node(x, None)
try:
self.last.next = current
except AttributeError:
self.first = current
self.last = current
else:
self.last = current
def print_list(self):
node = self.first
while node:
print node.value
node = node.next
ll = LinkedList()
ll.add("1st")
ll.add("2nd")
ll.add("3rd")
ll.add("4th")
ll.add("5th")
ll.print_list()
# Result:
# 1st
# 2nd
# 3rd
# 4th
# 5th
My 2 cents
class Node:
def __init__(self, value=None, next=None):
self.value = value
self.next = next
def __str__(self):
return str(self.value)
class LinkedList:
def __init__(self):
self.first = None
self.last = None
def add(self, x):
current = Node(x, None)
try:
self.last.next = current
except AttributeError:
self.first = current
self.last = current
else:
self.last = current
def print_list(self):
node = self.first
while node:
print node.value
node = node.next
ll = LinkedList()
ll.add("1st")
ll.add("2nd")
ll.add("3rd")
ll.add("4th")
ll.add("5th")
ll.print_list()
# Result:
# 1st
# 2nd
# 3rd
# 4th
# 5th
回答 25
enter code here
enter code here
class node:
def __init__(self):
self.data = None
self.next = None
class linked_list:
def __init__(self):
self.cur_node = None
self.head = None
def add_node(self,data):
new_node = node()
if self.head == None:
self.head = new_node
self.cur_node = new_node
new_node.data = data
new_node.next = None
self.cur_node.next = new_node
self.cur_node = new_node
def list_print(self):
node = self.head
while node:
print (node.data)
node = node.next
def delete(self):
node = self.head
next_node = node.next
del(node)
self.head = next_node
a = linked_list()
a.add_node(1)
a.add_node(2)
a.add_node(3)
a.add_node(4)
a.delete()
a.list_print()
enter code here
enter code here
class node:
def __init__(self):
self.data = None
self.next = None
class linked_list:
def __init__(self):
self.cur_node = None
self.head = None
def add_node(self,data):
new_node = node()
if self.head == None:
self.head = new_node
self.cur_node = new_node
new_node.data = data
new_node.next = None
self.cur_node.next = new_node
self.cur_node = new_node
def list_print(self):
node = self.head
while node:
print (node.data)
node = node.next
def delete(self):
node = self.head
next_node = node.next
del(node)
self.head = next_node
a = linked_list()
a.add_node(1)
a.add_node(2)
a.add_node(3)
a.add_node(4)
a.delete()
a.list_print()
回答 26
我的双重链接列表对于新手来说是可以理解的。如果您熟悉C语言中的DS,那么这很容易理解。
# LinkedList..
class node:
def __init__(self): ##Cluster of Nodes' properties
self.data=None
self.next=None
self.prev=None
class linkedList():
def __init__(self):
self.t = node() // for future use
self.cur_node = node() // current node
self.start=node()
def add(self,data): // appending the LL
self.new_node = node()
self.new_node.data=data
if self.cur_node.data is None:
self.start=self.new_node //For the 1st node only
self.cur_node.next=self.new_node
self.new_node.prev=self.cur_node
self.cur_node=self.new_node
def backward_display(self): //Displays LL backwards
self.t=self.cur_node
while self.t.data is not None:
print(self.t.data)
self.t=self.t.prev
def forward_display(self): //Displays LL Forward
self.t=self.start
while self.t.data is not None:
print(self.t.data)
self.t=self.t.next
if self.t.next is None:
print(self.t.data)
break
def main(self): //This is kind of the main
function in C
ch=0
while ch is not 4: //Switch-case in C
ch=int(input("Enter your choice:"))
if ch is 1:
data=int(input("Enter data to be added:"))
ll.add(data)
ll.main()
elif ch is 2:
ll.forward_display()
ll.main()
elif ch is 3:
ll.backward_display()
ll.main()
else:
print("Program ends!!")
return
ll=linkedList()
ll.main()
尽管可以在此代码中添加更多简化功能,但我认为原始的实现方式会更容易抓住。
my double Linked List might be understandable to noobies.
If you are familiar with DS in C, this is quite readable.
# LinkedList..
class node:
def __init__(self): ##Cluster of Nodes' properties
self.data=None
self.next=None
self.prev=None
class linkedList():
def __init__(self):
self.t = node() // for future use
self.cur_node = node() // current node
self.start=node()
def add(self,data): // appending the LL
self.new_node = node()
self.new_node.data=data
if self.cur_node.data is None:
self.start=self.new_node //For the 1st node only
self.cur_node.next=self.new_node
self.new_node.prev=self.cur_node
self.cur_node=self.new_node
def backward_display(self): //Displays LL backwards
self.t=self.cur_node
while self.t.data is not None:
print(self.t.data)
self.t=self.t.prev
def forward_display(self): //Displays LL Forward
self.t=self.start
while self.t.data is not None:
print(self.t.data)
self.t=self.t.next
if self.t.next is None:
print(self.t.data)
break
def main(self): //This is kind of the main
function in C
ch=0
while ch is not 4: //Switch-case in C
ch=int(input("Enter your choice:"))
if ch is 1:
data=int(input("Enter data to be added:"))
ll.add(data)
ll.main()
elif ch is 2:
ll.forward_display()
ll.main()
elif ch is 3:
ll.backward_display()
ll.main()
else:
print("Program ends!!")
return
ll=linkedList()
ll.main()
Though many more simplifications can be added to this code, I thought a raw implementation would me more grabbable.
回答 27