列表

参考链接:https://python-web-guide.readthedocs.io/zh/latest/algorithms/algorithms.html#recursion

遗留问题:实现有序列表的列表迭代器,抽象unittest的测试用例,9.9的编程题

列表有基于索引,位置(游标cursor),内容的三种类型的操作。

#! /usr/bin/env python
# -*- coding: utf-8 -*-

'''
@author: liudaoqiang
@file: studycase
@time: 2018/9/14 7:02
'''

import unittest

class Node(object):

	def __init__(self, data, next):
		self._data = data
		self._next = next

	def  __iter__(self):
		cursor = self
		while cursor != None:
			yield cursor._data
			cursor = cursor._next


class Array(object):

	def __init__(self, capacity, fillValue=None):
		self._items = list()
		for index in range(capacity):
			self._items.append(fillValue)

	def __iter__(self):
		return iter(self._items)

	def __len__(self):
		return len(self._items)

	def __getitem__(self, index):
		return self._items[index]

	def __setitem__(self, index, newItem):
		self._items[index] = newItem

	def __str__(self):
		return str(self._items)


class TwoWayNode(Node):
	def __init__(self, data, prev=None, next=None):
		Node.__init__(self, data, next)
		self._prev = prev


class AbstractCollection(object):

	def __init__(self, sourceCollection):
		self._size = 0
		for item in sourceCollection:
			self.add(item)

	def isEmpty(self):
		return self._size == 0

	def __add__(self, other):
		result = type(self)(self)
		for item in other:
			result.add(item)
		return result

	def __len__(self):
		return self._size

	def __str__(self):
		return str(self)

	def __eq__(self, other):
		if self is other: return True
		if type(self) != type(other) or\
			len(self) != len(other):
			return False
		else:
			otherIter = iter(other)
			for item in self:
				if item != next(otherIter):
					return False
			return True


class AbstractList(AbstractCollection):
	"""An abstract list implementation"""

	def __init__(self, sourceCollection):
		"""Maintains a count of modification to the list"""
		self._modCount = 0
		AbstractCollection.__init__(self, sourceCollection)

	def getModCount(self):
		"""Returns the count of modifications to the list"""
		return self._modCount

	def incModConut(self):
		"""Increments the count of modifications to the list"""
		self._modCount += 1

	def index(self, item):
		"""
		Preconditon: item is in the list
		Returns the position of item
		Raises: ValueError if the item is not in the list
		:param item:
		:return:
		"""
		position = 0
		for data in self:
			if data == item:
				return position
			else:
				position += 1
		if position == len(self):
			raise ValueError(str(item) + "not in list")

	def add(self, item):
		"""Adds the item to the end of the list"""
		self.insert(len(self), item)

	def remove(self, item):
		"""
		Precondition: item is in self.
		Raises: ValueError if item is not in self.
		PostPosition: item is removed from self
		:param item:
		:return:
		"""
		position = self.index(item)
		self.pop(position)


class LinkedList(AbstractList):

	def __init__(self, sourceCollection=None):
		# 初始化一个哨兵节点
		self._head = TwoWayNode(10)
		self._head._prev = self._head
		self._head._next = self._head
		AbstractList.__init__(self, sourceCollection)

	def __iter__(self):
		cursor = self._head._next
		while cursor != self._head:
			yield cursor._data
			cursor = cursor._next

	def getNode(self, i):
		if i == len(self):
			# 访问头节点常数时间
			return self._head
		if i == len(self) - 1:
			# 哨兵节点的prev指向最后一个数据节点
			return self._head._prev
		probe = self._head._next
		while i > 0:
			probe = probe._next
			i -= 1
		return probe

	def __setitem__(self, i, item):
		if i < 0 or i >= len(self):
			raise IndexError("List index out of range")
		self.getNode(i)._data = item

	def __getitem__(self, i):
		if i < 0 or i >= len(self):
			raise IndexError("List index out of range")
		return self.getNode(i)._data

	def __str__(self):
		result = ""
		Iterator = iter(self)
		for i in range(self._size):
			result += str(Iterator.__next__())
		result = "{" + ' ,'.join(result) + "}"
		return result

	def insert(self, i, item):
		"""Insert the item at position i"""
		if i < 0: i = 0
		if i > len(self): i = len(self)
		theNode = self.getNode(i)
		newNode = TwoWayNode(item, theNode._prev, theNode)
		theNode._prev._next = newNode
		theNode._prev = newNode
		self._size += 1
		self.incModConut()

	def pop(self, i=None):
		if i == None : i = len(self) - 1
		if i >= len(self) or i < 0:
			raise IndexError("List Index out of range")
		oldNode = self.getNode(i)
		oldNode._next._prev = oldNode._prev
		oldNode._prev._next = oldNode._next
		self._size -= 1
		self.incModConut()
		return oldNode._data

	def replace(self, i, item):
		if i < 0 or i > len(self):
			raise IndexError("Index out of range")
		else:
			self.getNode(i)._data = item

	def listIterator(self):
		return LinkedListIterator(self)

# 双链表的列表迭代器
class LinkedListIterator(object):
	def __init__(self, backingStore):
		"""Set the initial state of the list iterator"""
		self._backingStore = backingStore
		self._modCnt = backingStore.getModCount()
		self.first()

	def first(self):
		"""Resets the cursor to the beginning of the backing store"""
		self._cursor = 0
		# 将游标的位置置于哨兵节点
		self._lastItemPos = -1

	def hasNext(self):
		# print(self._cursor, self._backingStore._size)
		return self._cursor < self._backingStore._size

	def next(self):
		if not self.hasNext():
			raise ValueError("No next item in list iterator")
		if self._modCnt != self._backingStore.getModCount():
			raise  AttributeError("Illegal modification of backingstore")
		probe = self._backingStore._head._next
		i = self._cursor + 1
		# print(self._cursor)
		while i > 1:
			probe = probe._next
			i -= 1
		data = probe._data
		# print(probe._data)
		self._lastItemPos = self._cursor
		self._cursor += 1
		# print("=")
		return data

	def last(self):
		self._cursor = self._backingStore._size
		self._lastItemPos = -1

	def hasPrevious(self):
		return self._cursor > 0

	def previous(self):
		if not self.hasPrevious():
			raise ValueError("No previous item in list iterator")
		if self._modCnt != self._backingStore.getModCount():
			raise AttributeError("Illegal modification of backing store")
		i = self._cursor - 1
		probe = self._backingStore._head._next
		while i > 0:
			probe = probe._next
			i -= 1
		self._lastItemPos = self._cursor
		self._cursor = self._cursor - 1
		data = probe._data
		return data

	def replace(self, item):
		if self._lastItemPos == -1:
			raise AttributeError("The current position is undefined")
		if self._modCnt != self._backingStore.getModCount():
			raise AttributeError("List has been modified illegally")
		i = self._cursor
		probe = self._backingStore._head._next
		while i > 1:
			probe = probe._next
			i -= 1
		probe._data = item
		self._lastItemPos = -1

	def insert(self, item):
		if self._modCnt != self._backingStore.getModCount():
			raise AttributeError("List has been modified illegally.")
		if self._lastItemPos == -1:
			self._backingStore.insert(self._backingStore._size - 1, item)
		else:
			self._backingStore.insert(self._lastItemPos, item)
		self._lastItemPos = -1
		self._modCnt += 1

	def remove(self):
		if self._lastItemPos == -1:
			raise AttributeError("The current position is undefined")
		if self._modCnt != self._backingStore.getModCount():
			raise AttributeError("List has been modified illegally")
		item = self._backingStore.pop(self._lastItemPos)

		# if the item removed was obtained via next, move cursor back
		if self._lastItemPos < self._cursor:
			self._cursor -= 1
		self._modCnt += 1
		self._lastItemPos = -1


class ArraySortedList(AbstractList):

	DEFAULT_CAPACITY = 10
	def __init__(self, sourceCollection=None):
		self._items = Array(ArraySortedList.DEFAULT_CAPACITY)
		AbstractList.__init__(self, sourceCollection)

	# Accessor methods
	def __iter__(self):
		cursor = 0
		while cursor < len(self):
			yield self._items[cursor]
			cursor += 1

	def __str__(self):
		result = ""
		for i in range(self._size):
			result += str(self._items[i]) + " "
		return result

	def __getitem__(self, i):
		if i < 0 or i >= len(self):
			raise IndexError("List index out of range")
		return self._items[i]

	def index(self, item):
		def insertSort(target, lyst):
			left = 0
			right = len(lyst) - 1
			while left <= right:
				middle = (left + right) // 2
				if lyst[middle] < item:
					left = middle - 1
				elif lyst[middle] > item:
					right = middle + 1
				else:
					return middle
			return -1

		if insertSort(self._items, item) == -1:
			raise AttributeError("item not in list")
		else:
			return insertSort(self._items, item)

	def add(self, item):
		if self._size == 0:
			self._items[0] = item
			self._size += 1
		else:
			if self._size >= ArraySortedList.DEFAULT_CAPACITY:
				temp = Array(self._size + 1)
				for i in range(self._size):
					temp[i] = self._items[i]
				self._items = temp
			j = self._size - 1
			while j >= 0:
				if item < self._items[j]:
					self._items[j + 1] = self._items[j]
					j -= 1
				else:
					break
			self._items[j + 1] = item
			self._size += 1


	def pop(self, i=None):
		if i == None: i = len(self) - 1
		if i < 0 or i >= len(self):
			raise IndexError("List index out of range")
		item = self._items[i]
		for i in range(i, len(self) - 1):
			self._items[i] = self._items[i + 1]
		self._size -= 1
		self.incModConut()
		return item

	"""有序列表不能搞列表迭代器"""
	# def sortedlistIterator(self):
	# 	return ArraySortedListIterator(self)


class ArrayList(AbstractList):
	"""An array-based list implementation"""

	DEFAULT_CAPACITY = 10
	def __init__(self, sourceCollection=None):
		self._items = Array(ArrayList.DEFAULT_CAPACITY)
		AbstractList.__init__(self, sourceCollection)

	#Accessor methods
	def __iter__(self):
		cursor = 0
		while cursor < len(self):
			yield self._items[cursor]
			cursor += 1

	def __str__(self):
		result = ""
		for i in range(self._size):
			result += str(self._items[i]) + " "
		return result

	def __getitem__(self, i):
		if i < 0 or i >= len(self):
			raise IndexError("List index out of range")
		return self._items[i]

	def __setitem__(self, i, value):
		if i < 0 or i >= len(self):
			raise IndexError("List index out of range")
		self._items[i] = value

	def insert(self, i, item):
		if i < 0: i = 0
		if i > len(self): i = len(self)
		if i < len(self):
			for j in range(len(self), i, -1):
				self._items[j] = self._items[j - 1]
		self._items[i] = item
		self._size += 1
		self.incModConut()

	def pop(self, i):
		if i == None: i = len(self) - 1
		if i < 0 or i >= len(self):
			raise IndexError("List index out of range")
		item = self._items[i]
		for i in range(i, len(self) - 1):
			self._items[i] = self._items[i + 1]
		self._size -= 1
		self.incModConut()
		return item

	def listIterator(self):
		return ArrayListIterator(self)


class ArrayListIterator(object):
	"""Represents the list state of the list iterator"""

	def __init__(self, backingStore):
		"""Set the initial state of the list iterator"""
		self._backingStore = backingStore
		self._modCnt = backingStore.getModCount()
		self.first()

	def first(self):
		"""Resets the cursor to the beginning of the backing store"""
		self._cursor = 0
		self._lastItemPos = -1

	def hasNext(self):
		return self._cursor < len(self._backingStore)

	def next(self):
		if not self.hasNext():
			raise ValueError("No next item in list iterator")
		if self._modCnt != self._backingStore.getModCount():
			raise  AttributeError("Illegal modification of backingstore")
		self._lastItemPos = self._cursor
		self._cursor += 1
		return self._backingStore[self._lastItemPos]

	def last(self):
		self._cursor = len(self._backingStore)
		self._lastItemPos = -1

	def hasPrevious(self):
		return self._cursor > 0

	def previous(self):
		if not self.hasPrevious():
			raise ValueError("No previous item in list iterator")
		if self._modCnt != self._backingStore.getModCount():
			raise AttributeError("Illegal modification of backing store")
		self._cursor -= 1
		self._lastItemPos = self._cursor
		return self._backingStore[self._lastItemPos]

	def replace(self, item):
		if self._lastItemPos == -1:
			raise AttributeError("The current position is undefined")
		if self._modCnt != self._backingStore.getModCount():
			raise AttributeError("List has been modified illegally")
		self._backingStore[self._lastItemPos] = item
		self._lastItemPos = -1

	def insert(self, item):
		if self._modCnt != self._backingStore.getModCount():
			raise AttributeError("List has been modified illegally.")
		if self._lastItemPos == -1:
			self._backingStore.add(item)
		else:
			self._backingStore.insert(self._lastItemPos, item)
		self._lastItemPos = -1
		self._modCnt += 1

	def remove(self):
		if self._lastItemPos == -1:
			raise AttributeError("The current position is undefined")
		if self._modCnt != self._backingStore.getModCount():
			raise AttributeError("List has been modified illegally")
		item = self._backingStore.pop(self._lastItemPos)

		# if the item removed was obtained via next, move cursor back
		if self._lastItemPos < self._cursor:
			self._cursor -= 1
		self._modCnt += 1
		self._lastItemPos = -1

class TestCase(unittest.TestCase):

	def test_LinkedListPrint(self):
		lyst = LinkedList(range(1, 9))
		print(list(range(1,9)))
		print("LinkedList:", lyst)
		self.assertEqual(1, lyst[0])
		self.assertEqual(8, lyst[7])

	def test_LinkedList_Printnext(self):
		lyst = LinkedList(range(1, 9))
		probe = lyst._head
		result = ""
		for i in range(len(lyst)):
			result += str(probe._next._data) + " "
			probe = probe._next
		print("print next:" + result)
		self.assertEqual(int(result[0]), 1)

	def test_LinkedList_PrintPrev(self):
		lyst = LinkedList(range(1, 9))
		probe = lyst._head
		result = ""
		for i in range(len(lyst)):
			result += str(probe._prev._data) + " "
			probe = probe._prev
		print("print prev:" + result)
		self.assertEqual(int(result[0]), 8)

	def test_LinkedList_Insert(self):
		lyst = LinkedList(range(1, 9))
		lyst.insert(2,9)
		self.assertEqual(lyst[2], 9)

	def test_LinkedList_Pop(self):
		lyst = LinkedList(range(1, 9))
		probe = lyst
		oldItem = probe.pop()
		self.assertEqual(oldItem, 8)
		print("probe:", probe)
		self.assertEqual(lyst.getNode(7), lyst._head)

	def test_LinkedList_PopAll(self):
		lyst = LinkedList(range(1, 9))
		probe = lyst
		i = len(probe) - 1
		while i >= 0:
			probe.pop()
			i -= 1
		print("Remove all mode:", probe)
		self.assertEqual(len(lyst), 0)

	def test_LinkedIterator_next(self):
		lyst = LinkedList(range(1,9))
		listIterator = LinkedListIterator(lyst)
		listIterator.first()
		self.assertEqual(listIterator.next(), 1)
		self.assertEqual(listIterator.next(), 2)

	def test_LinkedIterator_previous(self):
		lyst = LinkedList(range(1,9))
		listIterator = LinkedListIterator(lyst)
		listIterator.last()
		self.assertEqual(listIterator.previous(), 8)
		self.assertEqual(listIterator.previous(), 7)

	def test_LinkedIterator_remove(self):
		lyst = LinkedList(range(1,9))
		listIterator = LinkedListIterator(lyst)
		listIterator.first()
		listIterator.next()
		listIterator.remove()
		listIterator.first()
		self.assertEqual(lyst[0], 2)
		self.assertEqual(lyst[1], 3)
		self.assertEqual(len(lyst), 7)

	def test_LinkedIterator_insert(self):
		lyst = LinkedList(range(1,9))
		listIterator = LinkedListIterator(lyst)
		listIterator.first()
		listIterator.next()
		listIterator.insert(9)
		self.assertEqual(lyst[0],9)

	def test_LinkedIterator_replace(self):
		lyst = LinkedList(range(1, 9))
		listIterator = LinkedListIterator(lyst)
		listIterator.first()
		listIterator.next()
		listIterator.replace(10)
		self.assertEqual(lyst[0], 10)
		self.assertEqual(lyst[1], 2)

	def test_ArrayListIterator_next(self):
		lyst = ArrayList(range(1, 9))
		listIterator = ArrayListIterator(lyst)
		listIterator.first()
		self.assertEqual(listIterator.next(), 1)

	def test_ArrayListIterator_previous(self):
		lyst = ArrayList(range(1, 9))
		listIterator = ArrayListIterator(lyst)
		listIterator.last()
		listIterator.previous()
		self.assertEqual(listIterator.previous(), 7)

	def test_ArrayListIterator_hasprevious(self):
		lyst = ArrayList(range(1, 9))
		listIterator = ArrayListIterator(lyst)
		listIterator.first()
		self.assertEqual(listIterator.hasPrevious(), False)

	def test_ArrayListIterator_hasnext(self):
		lyst = ArrayList(range(1, 9))
		listIterator = ArrayListIterator(lyst)
		listIterator.last()
		self.assertEqual(listIterator.hasNext(), False)

	def test_ArrayListIterator_insert(self):
		lyst = ArrayList(range(1, 9))
		listIterator = ArrayListIterator(lyst)
		listIterator.first()
		listIterator.next()
		listIterator.insert(10)
		self.assertEqual(lyst[0], 10)

	def test_ArrayListIterator_remove(self):
		lyst = ArrayList(range(1, 9))
		listIterator = ArrayListIterator(lyst)
		listIterator.first()
		listIterator.next()
		listIterator.remove()
		self.assertEqual(lyst[0], 2)

	def test_ArrayListIterator_replace(self):
		lyst = ArrayList(range(1, 9))
		listIterator = ArrayListIterator(lyst)
		listIterator.first()
		listIterator.next()
		listIterator.replace(10)
		self.assertEqual(lyst[0], 10)

if __name__ == "__main__":
	unittest.main()

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值