fix few details, linked lists

This commit is contained in:
Mari Wahl 2014-08-26 22:59:54 -04:00
parent 2e28142075
commit eeeb3c4e4b
13 changed files with 352 additions and 515 deletions

Binary file not shown.

View File

@ -1,40 +1,49 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
''' Given a linked list, check if the nodes form a palindrome ''' ''' Given a linked list, check if the nodes form a palindrome '''
from linked_list_fifo import LinkList, Node from linked_list_fifo import LinkedListFIFO, Node
from node import Node
def isPal(l):
if len(l1) < 2:
return True
if l1[0] != l1[-1]:
return False
def isPal(l1):
if len(l1) < 2: return True
if l1[0] != l1[-1]: return False
return isPal(l1[1:-1]) return isPal(l1[1:-1])
def checkllPal(ll): def checkllPal(ll):
node = ll.head node = ll.head
l1 = [] l = []
while node: while node:
l1.append(node.value) l.append(node.value)
node = node.next node = node.pointer
return isPal(l1)
return isPal(l)
def main():
ll = LinkList()
l1 = [1, 2, 3, 2, 1]
for i in l1:
ll.addNode(i)
print(checkllPal(ll))
ll.addNode(2)
ll.addNode(3)
print(checkllPal(ll))
if __name__ == '__main__': if __name__ == '__main__':
main()
ll = LinkedListFIFO()
l1 = [1, 2, 3, 2, 1]
for i in l1:
ll.addNode(i)
assert(checkllPal(ll) == True)
ll.addNode(2)
ll.addNode(3)
assert(checkllPal(ll) == False)

View File

@ -1,72 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' Build a class for a circular linked list and implement a function to see whether
a linked list is circular'''
from linked_list_fifo import Node, LinkList
class Node(object):
def __init__(self, value = None, next = None):
self.value = value
self.next = next
class CircLinkList(object):
def __init__(self):
self.head = None
self.tail = None
self.lenght = 0
def addNode(self, value):
node = Node(value, self.head)
if not self.head:
self.head = node
if self.tail:
self.tail.next = node
self.tail = node
self.lenght += 1
def printList(self):
size = self.lenght
node = self.head
i = 0
while i < size:
print(node.value)
node = node.next
i += 1
def isCircularll(ll):
p1 = ll.head
p2 = ll.head
while p2 and p2.next:
p1 = p1.next
p2 = p2.next.next
if p1 == p2:
return True
return False
def main():
ll = CircLinkList()
for i in range(10):
ll.addNode(i)
ll.printList()
print(isCircularll(ll))
ll2 = LinkList()
for i in range(10):
ll2.addNode(i)
ll2.printList()
print(isCircularll(ll2))
if __name__ == '__main__':
main()

View File

@ -0,0 +1,57 @@
#!/usr/bin/python
__author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
''' implement a function to see whether a linked list is circular.
To implement this, we just need two pointers with different
paces (for example, one goes twice faster)'''
from linked_list_fifo import LinkedListFIFO
from node import Node
class cicularLinkedListFIFO(LinkedListFIFO):
def _add(self, value):
self.length += 1
node = Node(value, self.head)
if self.tail:
self.tail.pointer = node
self.tail = node
def isCircularll(ll):
p1 = ll.head
p2 = ll.head
while p2:
try:
p1 = p1.pointer
p2 = p2.pointer.pointer
except:
break
if p1 == p2:
return True
return False
if __name__ == '__main__':
ll = LinkedListFIFO()
for i in range(10):
ll.addNode(i)
ll._printList()
print(isCircularll(ll))
lcirc = cicularLinkedListFIFO()
for i in range(10):
lcirc.addNode(i)
print(isCircularll(lcirc))

View File

@ -1,53 +1,92 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail
''' Implement a double-linked list, which is very simple, we just need inherets from a Linked List Class and add an attribute for prev.''' __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
''' Implement a double-linked list, which is very simple, we just need inherits
from a Linked List Class and add an attribute for previous.'''
from linked_list_fifo import LinkedListFIFO
from linked_list_fifo import LinkList
class dNode(object): class dNode(object):
def __init__(self, value = None, next = None): def __init__(self, value=None, pointer=None, previous=None):
self.value = value self.value = value
self.next = next self.pointer = pointer
self.prev = None # THIS IS THE EXTRA ATTRIBUTE FOR DOUBLE L self.previous = previous
self.children = None # THIS IS NOT USED HERE, IS EXAMPLES WITH MANY LL INSIDE LLs
class dLinkList(LinkList):
def addNode(self, value):
node = dNode(value)
if not self.head:
self.head = node
if self.tail:
node.prev = self.tail # ADD THIS WHEN DOUBLE L
self.tail.next = node
self.tail = node
self.length += 1
def printListInverse(self): # THIS IS THE EXTRA METHOD FOR DOUBLE L class dLinkList(LinkedListFIFO):
# print each node's value, starting from tail
def printListInverse(self):
node = self.tail node = self.tail
while node: while node:
print(node.value) print(node.value)
node = node.prev try:
node = node.previous
except:
break
# add a node in a position different from head,
# ie, in the end of the list
def _add(self, value):
self.length += 1
node = dNode(value)
if self.tail:
self.tail.pointer = node
node.previous = self.tail
self.tail = node
# delete a node in some position
def _delete(self, node):
self.length -= 1
node.previous.pointer = node.pointer
if not node.pointer:
self.tail = node.previous
# locate node with some index
def _find(self, index):
node = self.head
i = 0
while node and i < index:
node = node.pointer
i += 1
return node, i
# delete nodes in general
def deleteNode(self, index):
if not self.head or not self.head.pointer:
self._deleteFirst()
else:
node, i = self._find(index)
if i == index:
self._delete(node)
else:
print('Node with index {} not found'.format(index))
from collections import Counter
def main():
ll = dLinkList()
for i in range(1, 10):
ll.addNode(i)
print('Printing the list...')
ll.printList()
print('Now, printing the list inversely...')
ll.printListInverse()
if __name__ == '__main__': if __name__ == '__main__':
main()
from collections import Counter
ll = dLinkList()
for i in range(1, 5):
ll.addNode(i)
print('Printing the list...')
ll._printList()
print('Now, printing the list inversely...')
ll.printListInverse()
print('The list after adding node with value 15')
ll._add(15)
ll._printList()
print("The list after deleting everything...")
for i in range(ll.length-1, -1, -1):
ll.deleteNode(i)
ll._printList()

View File

@ -1,105 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' Find the mth-to-last element of a linked list.
One option is having two pointers, separated by m. P1 start at the roots (p1 = self.root) and p2 is m-behinf pointer, which is created when p1 is at m. When p1 reach the end, p2 is the node. '''
from linked_list_fifo import Node
class LinkList(object):
def __init__(self):
self.head = None
self.tail = None
self.lenght = 0
def addNode(self, value):
node = Node(value)
if not self.head:
self.head = node
if self.tail:
self.tail.next = node
self.tail = node
self.lenght += 1
def removeNode(self, index):
prev = None
node = self.head
i = 0
while node and i < index:
prev = node
node = node.next
i += 1
if i == index:
if not prev:
self.head = node.next
else:
prev.next = node.next
self.lenght -= 1
else:
print('Index not found')
def findkth_from_begin(self, k):
node = self.head
i = 0
while node and i < k:
node = node.next
i += 1
while node:
print(node.value)
node = node.next
def findkth_to_last(self, k):
node = self.head
key = self.lenght - k
i = 0
while node and i < key:
node = node.next
i += 1
print(node.value)
def findkth_to_last_2pointers(self, k):
node = self.head
pointer = self.head
i = 0
while pointer and i < k:
pointer = pointer.next
i += 1
while pointer:
node = node.next
pointer = pointer.next
print(node.value)
def findkth_to_last_2pointers2(self, k):
p1 = self.head
p2 = self.head
i = 0
while p1:
if i >= k: # ---> notice >= not >!
p2 = p2.next
p1 = p1.next
i += 1
print(p2.value)
def main():
ll = LinkList()
for i in range(1, 11):
ll.addNode(i)
# list is 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
# so 0th from last is 11, 1th to last is 10,
# 2th from last is 9!
print('Finding from begin...')
ll.findkth_from_begin(2)
print('Finding to last, case 1...')
ll.findkth_to_last(2) #9
print('Finding to last, case 2...')
ll.findkth_to_last_2pointers(2)
print('Finding to last, case 3...')
ll.findkth_to_last_2pointers2(2)
if __name__ == '__main__':
main()

View File

@ -0,0 +1,42 @@
#!/usr/bin/python
__author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
''' Find the mth-to-last element of a linked list.
One option is having two pointers, separated by m. P1 start at the roots
(p1 = self.root) and p2 is m-behinf pointer, which is created when p1 is at m.
When p1 reach the end, p2 is the node. '''
from linked_list_fifo import LinkedListFIFO
from node import Node
class LinkedListFIFO_find_kth(LinkedListFIFO):
def find_kth_to_last(self, k):
p1, p2 = self.head, self.head
i = 0
while p1:
if i > k:
try:
p2 = p2.pointer
except:
break
p1 = p1.pointer
i += 1
return p2.value
if __name__ == '__main__':
ll = LinkedListFIFO_find_kth()
for i in range(1, 11):
ll.addNode(i)
print('The Linked List:')
print(ll._printList())
k = 3
k_from_last = ll.find_kth_to_last(k)
print("The %dth element to the last of the LL of size %d is %d" %(k, ll.length, k_from_last))

View File

@ -1,65 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
from node import Node
class UnorderedList(object):
def __init__(self):
self.head = None
def add(self, item):
temp = Node(item)
temp.setNext(self.head)
self.head = temp
def length(self):
current = self.head
count = 0
while current != None:
count = count + 1
current = current.getNext()
return count
def search(self, item):
current = self.head
found = False
while current != None and not found:
if current.getData() == item:
found = True
else:
current = current.getNext()
return found
def remove(self, item):
current = self.head
previous = None
found = False
while not found:
if current.getData() == item:
found = True
else:
previous = current
current = current.getNext()
if previous == None:
self.head = current.getNext()
else:
previous.setNext(current.getNext())
def test_UnorderedList(module_name='this module'):
llist = UnorderedList()
llist.add(31)
llist.add(22)
llist.add(10)
assert(llist.search(22) == True)
llist.remove(22)
assert(llist.search(22) == False)
s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed'))
if __name__ == '__main__':
test_UnorderedList()

View File

@ -1,97 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
from Node import Node
class OrderedList:
""" The structure of an ordered list is a collection of items where each item
holds a relative position that is based upon some underlying characteristic of
the item. The ordering is typically either ascending or descending and we assume
that list items have a meaningful comparison operation that is already defined.
Many of the ordered list operations are the same as those of the unordered list.
"""
def __init__(self):
self.head = None
def add(self,item):
''' this method is different from linked list '''
current = self.head
previous = None
stop = False
while current != None and not stop:
if current.getData() > item:
stop = True
else:
previous = current
current = current.getNext()
temp = Node(item)
if previous == None:
temp.setNext(self.head)
self.head = temp
else:
temp.setNext(current)
previous.setNext(temp)
def length(self):
current = self.head
count = 0
while current != None:
count = count + 1
current = current.getNext()
return count
def search(self,item):
''' this method is different from linked list '''
current = self.head
found = False
stop = False
while current != None and not found and not stop:
if current.getData() == item:
found = True
else:
if current.getData() > item:
stop = True
else:
current = current.getNext()
return found
def remove(self,item):
current = self.head
previous = None
found = False
while not found:
if current.getData() == item:
found = True
else:
previous = current
current = current.getNext()
if previous == None:
self.head = current.getNext()
else:
previous.setNext(current.getNext())
def test_OrderedList(module_name='this module'):
olist = OrderedList()
olist.add(31)
olist.add(22)
olist.add(10)
assert(olist.search(22) == True)
olist.remove(22)
assert(olist.search(22) == False)
s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed'))
if __name__ == '__main__':
test_OrderedList()

View File

@ -0,0 +1,58 @@
#!/usr/bin/python
__author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
''' This function divides a linked list in a value, where everything smaller than this value
goes to the front, and everything large goes to the back:'''
from linked_list_fifo import LinkedListFIFO
from node import Node
def partList(ll, n):
more = LinkedListFIFO()
less = LinkedListFIFO()
node = ll.head
while node:
item = node.value
if item < n:
less.addNode(item)
elif item > n:
more.addNode(item)
node = node.pointer
less.addNode(n)
nodemore = more.head
while nodemore:
less.addNode(nodemore.value)
nodemore = nodemore.pointer
return less
if __name__ == '__main__':
ll = LinkedListFIFO()
l = [6, 7, 3, 4, 9, 5, 1, 2, 8]
for i in l:
ll.addNode(i)
print('Before Part')
ll._printList()
print('After Part')
newll = partList(ll, 6)
newll._printList()

View File

@ -1,45 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' This function partionate a linked list in a value, where everything smaller than this value
goes to the front, and everything large goes to the back:'''
from linked_list_fifo import LinkList, Node
def partList(ll, n):
more = LinkList()
less = LinkList()
node_old = ll.head
while node_old:
item = node_old.value
if item < n:
less.addNode(item)
elif item > n:
more.addNode(item)
node_old = node_old.next
less.addNode(n)
nodemore = more.head
while nodemore:
less.addNode(nodemore.value)
nodemore = nodemore.next
return less
def main():
ll = LinkList()
l1 = [6, 7, 3, 4, 9, 5, 1, 2, 8]
for i in l1:
ll.addNode(i)
print('Before Part')
ll.printList()
print('After Part')
newll = partList(ll, 6)
newll.printList()
if __name__ == '__main__':
main()

View File

@ -0,0 +1,86 @@
#!/usr/bin/python
__author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
''' Supposing two linked lists representing numbers, such that in each of their
nodes they carry one digit. This function sums the two numbers that these
two linked lists represent, returning a third list representing the sum:'''
from linked_list_fifo import LinkedListFIFO
from node import Node
class LinkedListFIFOYield(LinkedListFIFO):
# print each node's value, starting from the head
def _printList(self):
node = self.head
while node:
yield(node.value)
node = node.pointer
def sumlls(l1, l2):
lsum = LinkedListFIFOYield()
dig1 = l1.head
dig2 = l2.head
pointer = 0
while dig1 and dig2:
d1 = dig1.value
d2 = dig2.value
sum_d = d1 + d2 + pointer
if sum_d > 9:
pointer = sum_d//10
lsum.addNode(sum_d%10)
else:
lsum.addNode(sum_d)
pointer = 0
dig1 = dig1.pointer
dig2 = dig2.pointer
if dig1:
sum_d = pointer + dig1.value
if sum_d > 9:
lsum.addNode(sum_d%10)
else:
lsum.addNode(sum_d)
dig1 = dig1.pointer
if dig2:
sum_d = pointer + dig2.value
if sum_d > 9:
lsum.addNode(sum_d%10)
else:
lsum.addNode(sum_d)
dig2 = dig2.pointer
return lsum
if __name__ == '__main__':
l1 = LinkedListFIFOYield() # 2671
l1.addNode(1)
l1.addNode(7)
l1.addNode(6)
l1.addNode(2)
l2 = LinkedListFIFOYield() # 455
l2.addNode(5)
l2.addNode(5)
l2.addNode(4)
lsum = sumlls(l1, l2)
l = list(lsum._printList())
for i in reversed(l):
print i

View File

@ -1,70 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' Supposing two linked lists represening numbers, such that in each of their
nodes they carry one digit. This function sums the two numbers that these
two linked lists represent, returning a third list representing the sum:'''
from linked_list_fifo import Node, LinkList
def sumlls(l1, l2):
lsum = LinkList()
dig1 = l1.head
dig2 = l2.head
next = 0
while dig1 and dig2:
d1 = dig1.value
d2 = dig2.value
sum_d = d1 + d2 + next
if sum_d > 9:
next = sum_d//10
lsum.addNode(sum_d%10)
else:
lsum.addNode(sum_d)
next = 0
dig1 = dig1.next
dig2 = dig2.next
if dig1:
sum_d = next + dig1.value
if sum_d > 9:
lsum.addNode(sum_d%10)
else:
lsum.addNode(sum_d)
dig1 = dig1.next
if dig2:
sum_d = next + dig2.value
if sum_d > 9:
lsum.addNode(sum_d%10)
else:
lsum.addNode(sum_d)
dig2 = dig2.next
return lsum
def main():
l1 = LinkList() # 2671
l1.addNode(1)
l1.addNode(7)
l1.addNode(6)
l1.addNode(2)
l2 = LinkList() # 455
l2.addNode(5)
l2.addNode(5)
l2.addNode(4)
lsum = sumlls(l1, l2)
lsum.printList()# 3126
if __name__ == '__main__':
main()