用链表实现无序表
- 链表实现:节点Node
- 每个节点至少要包含2个信息:数据项本身,以及指向下一个节点的引用信息。
- next为None的意义是指没有下一个节点了
class Node:
def __init__(self, initdata):
self.data = initdata
self.next = None
def getData(self):
return self.data
def getNext(self):
return self.next
def setData(self, newdata):
self.data = newdata
def setNext(self,newnext):
self.next = newnext
temp = Node(93)
temp.getData()
93
- 链表实现:无序表UnorderedList
- 可以采用链接节点的方式构建数据集来实现无序表
- 链表的第一个和最后一个节点最重要
- 如果像访问链表中的所有节点,就必须从第一个节点开始沿着链接遍历下去
- 所以无序表必须要有对第一个节点的引用信息
- 设立一个属性head,保存对第一个节点的引用
- 空表的head为None
class UnorderedList:
def __init__(self):
self.head = None
mylist = UnorderedList()
print(mylist.head)
None
- 随着数据项的加入,无序表的head始终指向链条中的第一个节点
- 注意:无序表对象本身并不包含数据项(数据项在节点中),其中包含的head只是对首个节点的引用。
- 所以isEmpty()方法很容易实现:return self.head == None
- add():向无序表中添加数据项 O(1)
- 无序表中没有限定数据项之间的顺序,新数据想可以加入到原表中的任何位置
- 因为想要访问到整条链上的所有数据项,必须从表头开始,所以添加新数据项最快捷的位置是表头,整条链的首位置。
- size():从链条头开始遍历到表尾同时用变量累加经过的节点个数 O(n)
- search():从链头开始遍历到表尾,同时判断当前节点的数据项是否是目标 O(n)
- remove():首先要找到item,过程同search(),但在删除节点时,需要特别注意:
- 两种情况分析:
- current是首个节点:表头head指向current的下一个节点
- current是位于链条中间的节点:前一个节点的next指向current的下一个节点
class Node:
def __init__(self, initdata):
self.data = initdata
self.next = None
def getData(self):
return self.data
def getNext(self):
return self.next
def setData(self, newdata):
self.data = newdata
def setNext(self,newnext):
self.next = newnext
class UnorderedList:
def __init__(self):
self.head = None
def isEmpty(self):
return self.head == None
def add(self, item):
temp = Node(item)
temp.setNext(self.head)
self.head = temp
def size(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())
mylist = UnorderedList()
mylist.add(31)
mylist.add(77)
mylist.add(17)
mylist.add(93)
mylist.add(26)
mylist.add(54)
print(mylist.size())
print(mylist.search(17))
mylist.remove(17)
print(mylist.search(17))
print(mylist.size())
6
True
False
5
class Node:
def __init__(self, initdata):
self.data = initdata
self.next = None
def getData(self):
return self.data
def getNext(self):
return self.next
def setData(self, newdata):
self.data = newdata
def setNext(self,newnext):
self.next = newnext
class UnorderedList:
def __init__(self):
self.head = None
def isEmpty(self):
return self.head == None
def add(self, item):
temp = Node(item)
temp.setNext(self.head)
self.head = temp
def size(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 append(self, item):
temp = Node(item)
current = self.head
while current.getNext() != None:
current = current.getNext()
current.next = temp
def index(self, item):
count = 0
current = self.head
while current != None:
if current.data == item:
return count
else:
count = count + 1
current = current.getNext()
return None
def insert(self, item, pos):
current = self.head
nex = None
temp = Node(item)
count = 0
if pos == 0:
temp.setNext(self.head)
self.head = temp
else:
while count != pos - 1:
count = count + 1
current = current.getNext()
nex = current.getNext()
temp.setNext(nex)
current.setNext(temp)
def pop(self,pos = -1):
current = self.head
count = 0
nex = None
num = self.size()
if pos == 0:
item = current.data
self.head = current.getNext()
elif pos == -1:
while count != num - 2:
count = count + 1
current = current.getNext()
nex = current.getNext()
item = nex.getData()
current.setNext(None)
else:
while count != pos - 1:
count = count + 1
current = current.getNext()
nex = current.getNext()
item = nex.getData()
current.setNext(nex.getNext())
return item
mylist = UnorderedList()
mylist.add(31)
mylist.add(77)
print(mylist.size())
mylist.append(23)
print(mylist.size())
print(mylist.index(23))
mylist.insert(6,0)
print(mylist.index(6))
mylist.insert(66,1)
print(mylist.index(66))
print(mylist.index(31))
print(mylist.pop(0))
print(mylist.pop(2))
print(mylist.pop())
2
3
2
0
1
3
6
31
23
用链表实现有序表
- 同样采用链表方法实现,Node定义相同。
- OrderedList也设置一个head来保存链表表头的引用
class Node:
def __init__(self, initdata):
self.data = initdata
self.next = None
def getData(self):
return self.data
def getNext(self):
return self.next
def setData(self, newdata):
self.data = newdata
def setNext(self,newnext):
self.next = newnext
class OrderedList:
def __init__(self):
self.head = None
- 对于isEmpty()/size()/remove()函数与节点的次序无关,其实现同UnorderedList一样。
- search()/add()方法则需要修改
- search():在无序表中,如果需要查找的数据项不存在,则会搜索整个链表,直到链尾;而对于有序表来说,可以利用节点有序排列的特性,来为search()节省不存在数据项的查找时间。
- 一旦当前节点的数据项大于所要查找的数据项,则说明链表后面已经不可能再有要查找的数据项,可以直接返回False。
- add():改变最大。因为add方法必须保证加入的数据项添加在合适的位置,以维护整个链表的有序性。
- 涉及到插入位置是在当前节点之前,需要引入一个previous的引用,跟随当前节点current
class Node:
def __init__(self, initdata):
self.data = initdata
self.next = None
def getData(self):
return self.data
def getNext(self):
return self.next
def setData(self, newdata):
self.data = newdata
def setNext(self,newnext):
self.next = newnext
class OrderedList:
def __init__(self):
self.head = None
def isEmpty(self):
return self.head == None
def size(self):
current = self.head
count = 0
while current != None:
count = count + 1
current = current.getNext()
return count
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 search(self, item):
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 add(self, item):
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)
链表实现的算法分析
- 主要看相应的方法是否涉及到链表的遍历
- 对一个包含节点数为n的链表:
- isEmpty():O(1),因为仅需要检查head是否为None
- size():O(n),需要从表头遍历到表尾
- search()/remove()以及有序表的add()方法:O(n),因为涉及到链表的遍历。
- 无序表的add()方法:O(1),因为仅需要插入到表头
- 链表实现的List,与Python内置的列表数据类型,在有些相同方法的实现上的时间复杂度不同,主要是因为Python内置的列表数据类型是基于顺序存储来实现的,并进行了优化。