Linked_list in python
the provided structure of link
class Link:
"""A linked list.
>>> s = Link(1)
>>> s.first
1
>>> s.rest is Link.empty
True
>>> s = Link(2, Link(3, Link(4)))
>>> s.first = 5
>>> s.rest.first = 6
>>> s.rest.rest = Link.empty
>>> s # Displays the contents of repr(s)
Link(5, Link(6))
>>> s.rest = Link(7, Link(Link(8, Link(9))))
>>> s
Link(5, Link(7, Link(Link(8, Link(9)))))
>>> print(s) # Prints str(s)
<5 7 <8 9>>
"""
empty = ()
def __init__(self, first, rest=empty):
assert rest is Link.empty or isinstance(rest, Link)
self.first = first
self.rest = rest
def __repr__(self):
if self.rest is not Link.empty:
rest_repr = ', ' + repr(self.rest)
else:
rest_repr = ''
return 'Link(' + repr(self.first) + rest_repr + ')'
def __str__(self):
string = '<'
while self.rest is not Link.empty:
string += str(self.first) + ' '
self = self.rest
return string + str(self.first) + '>'
Problem 2.1: Store Digits (100pts)
Write a function store_digits that takes in an integer n and returns a linked list where each element of the list is a digit of n. Your solution should run in Linear time in the length of its input.
Note: You may not use str, repr or reversed in your implementation.
def store_digits(n):
"""Stores the digits of a positive number n in a linked list.
>>> s = store_digits(0)
>>> s
Link(0)
>>> store_digits(2345)
Link(2, Link(3, Link(4, Link(5))))
>>> store_digits(8760)
Link(8, Link(7, Link(6, Link(0))))
>>> # a check for restricted functions
>>> import inspect, re
>>> cleaned = re.sub(r"#.*\\n", '', re.sub(r'"{3}[\s\S]*?"{3}', '', inspect.getsource(store_digits)))
>>> print("Do not steal chicken!") if any([r in cleaned for r in ["str", "repr", "reversed"]]) else None
"""
"*** YOUR CODE HERE ***"
right solution
def store_digits(n):
"""Stores the digits of a positive number n in a linked list.
>>> s = store_digits(0)
>>> s
Link(0)
>>> store_digits(2345)
Link(2, Link(3, Link(4, Link(5))))
>>> store_digits(8760)
Link(8, Link(7, Link(6, Link(0))))
>>> # a check for restricted functions
>>> import inspect, re
>>> cleaned = re.sub(r"#.*\\n", '', re.sub(r'"{3}[\s\S]*?"{3}', '', inspect.getsource(store_digits)))
>>> print("Do not steal chicken!") if any([r in cleaned for r in ["str", "repr", "reversed"]]) else None
"""
temp=Link(n%10)
n//=10
while n:
temp=Link(n%10,temp)
n//=10
return temp
wrong solution
def store_digits(n):
"""Stores the digits of a positive number n in a linked list.
>>> s = store_digits(0)
>>> s
Link(0)
>>> store_digits(2345)
Link(2, Link(3, Link(4, Link(5))))
>>> store_digits(8760)
Link(8, Link(7, Link(6, Link(0))))
>>> # a check for restricted functions
>>> import inspect, re
>>> cleaned = re.sub(r"#.*\\n", '', re.sub(r'"{3}[\s\S]*?"{3}', '', inspect.getsource(store_digits)))
>>> print("Do not steal chicken!") if any([r in cleaned for r in ["str", "repr", "reversed"]]) else None
"""
"*** YOUR CODE HERE ***"
''' if n<10:
return Link(n)
else:
temp=store_digits(n//10)
head=temp
while(temp.rest!=Link.empty):
temp=temp.rest
temp.rest=Link(n%10)
return head
'''
if n<10:
return Link(n)
else:
return Link(n%10,store_digits(n//10))
#顺序相反了
A right but inefficient solution
def store_digits(n):
if n < 10:
return Link(n)
else:
temp = store_digits(n // 10)
head = temp
while temp.rest != Link.empty:
temp = temp.rest
temp.rest = Link(n % 10)
return head
Problem 2.2: Reverse (100 pts)
Write a function reverse which takes in a linked list lnk, reverses the order of it and returns the reversed list(i.e. return a new reference to the head of the reversed list). Your implementation should mutate the original linked list. DO NOT create any new linked lists.
You may not just simply exchange the first to reverse the list. On the contrary, you should make change on rest.
There is more than one way to solve this problem. Can you come up with more solutions?
def reverse(lnk):
""" Reverse a linked list.
>>> a = Link(1, Link(2, Link(3)))
>>> # Disallow the use of making new Links before calling reverse
>>> Link.__init__, hold = lambda *args: print("Do not steal chicken!"), Link.__init__
>>> try:
... r = reverse(a)
... finally:
... Link.__init__ = hold
>>> print(r)
<3 2 1>
>>> a.first # Make sure you do not change first
1
"""
"*** YOUR CODE HERE ***"
solution1 using loop
def reverse(lnk):
""" Reverse a linked list.
>>> a = Link(1, Link(2, Link(3)))
>>> # Disallow the use of making new Links before calling reverse
>>> Link.__init__, hold = lambda *args: print("Do not steal chicken!"), Link.__init__
>>> try:
... r = reverse(a)
... finally:
... Link.__init__ = hold
>>> print(r)
<3 2 1>
>>> a.first # Make sure you do not change first
1
"""
"*** YOUR CODE HERE ***"
if lnk==Link.empty:
return lnk
else:
prev,curr,next=Link.empty,lnk,Link.empty
while curr!=Link.empty:
next=curr.rest
curr.rest=prev
prev=curr
curr=next
return prev # return the prev node
solution2 using recursion
def reverse(lnk):
""" Reverse a linked list.
>>> a = Link(1, Link(2, Link(3)))
>>> # Disallow the use of making new Links before calling reverse
>>> Link.__init__, hold = lambda *args: print("Do not steal chicken!"), Link.__init__
>>> try:
... r = reverse(a)
... finally:
... Link.__init__ = hold
>>> print(r)
<3 2 1>
>>> a.first # Make sure you do not change first
1
"""
"*** YOUR CODE HERE ***"
def helper(lnk,prev=Link.empty):
if lnk==Link.empty:
return prev
else:
next=lnk.rest
lnk.rest=prev
return helper(next,lnk)
return helper(lnk)