python有序列表无序列表区别_用Python链表实现有序表与无序表
用Python鏈表實(shí)現(xiàn)有序表與無(wú)序表
《數(shù)據(jù)結(jié)構(gòu)與算法》MOOC(北大地空)課堂筆記
2020.4
by dlnb526
啥是鏈表
鏈表,顧名思義,顧名思義,鏈表像鎖鏈一樣,由一節(jié)節(jié)節(jié)點(diǎn)連在一起,組成一條數(shù)據(jù)鏈。
為什么要使用鏈表?
在之前用了python中的列表(list)來(lái)實(shí)現(xiàn)各種數(shù)據(jù)結(jié)構(gòu),然而有的語(yǔ)言可能并沒(méi)有提供像python的列表一樣強(qiáng)大的功能,我們必須要自己實(shí)現(xiàn)列表。
無(wú)序列表
概述
列表可以看作是一個(gè)無(wú)序的列表。
無(wú)序,也就是說(shuō)它里面的元素沒(méi)有一定的順序,比如這樣一個(gè)列表:
a = [1,2,'ads',54,32]
這里面的每個(gè)元素沒(méi)有按照一定的規(guī)則排序,所以就叫無(wú)序。
無(wú)序列表應(yīng)該有以下的方法
list() 創(chuàng)建一個(gè)新的空列表。它不需要參數(shù),而返回一個(gè)空列表。
add(item) 將新項(xiàng)添加到列表,沒(méi)有返回值。假設(shè)元素不在列表中。
remove(item) 從列表中刪除元素。需要一個(gè)參數(shù),并會(huì)修改列表。此處假設(shè)元素在列表中。
search(item) 搜索列表中的元素。需要一個(gè)參數(shù),并返回一個(gè)布爾值。
isEmpty() 判斷列表是否為空。不需要參數(shù),并返回一個(gè)布爾值。
size() 返回列表的元素?cái)?shù)。不需要參數(shù),并返回一個(gè)整數(shù)。
append(item) 在列表末端添加一個(gè)新的元素。它需要一個(gè)參數(shù),沒(méi)有返回值。假設(shè)該項(xiàng)目不在列表中。
index(item) 返回元素在列表中的位置。它需要一個(gè)參數(shù),并返回位置索引值。
此處假設(shè)該元素原本在列表中。
insert(pos,item) 在指定的位置添加一個(gè)新元素。它需要兩個(gè)參數(shù),沒(méi)有返回值。假設(shè)該元素在列表中并不存在,并且列表有足夠的長(zhǎng)度滿足參數(shù)提供的索引需要。
pop() 從列表末端移除一個(gè)元素并返回它。它不需要參數(shù),返回一個(gè)元素。假設(shè)列表至少有一個(gè)元素。
pop(pos) 從指定的位置移除列表元素并返回它。它需要一個(gè)位置參數(shù),并返回一個(gè)元素。假設(shè)該元素在列表中。
節(jié)點(diǎn)
為了實(shí)現(xiàn)無(wú)序列表,我們采用鏈表的方式。
鏈表最基本的元素是節(jié)點(diǎn)。
每個(gè)節(jié)點(diǎn)對(duì)象必須持有至少兩條信息。
首先,節(jié)點(diǎn)必須包含列表元素本身。我們將這稱(chēng)為該節(jié)點(diǎn)的“數(shù)據(jù)區(qū)”(data field)。
此外,每個(gè)節(jié)點(diǎn)必須保持到下個(gè)節(jié)點(diǎn)的引用。
如果沒(méi)有下一個(gè)節(jié)點(diǎn),那我們就記錄為None
class Node:#節(jié)點(diǎn)這個(gè)類(lèi)~
def __init__(self,initdata):
self.data = initdata
self.next = None#初始化的時(shí)候頭節(jié)點(diǎn)后面沒(méi)有節(jié)點(diǎn)了
def getData(self):
return self.data #節(jié)點(diǎn)可以獲取自身數(shù)據(jù)
def getNext(self):
return self.next #節(jié)點(diǎn)可以獲取指向的下一個(gè)節(jié)點(diǎn)
def setData(self,newdata):
self.data = newdata
def setNext(self,newnext):#節(jié)點(diǎn)可以對(duì)下一個(gè)節(jié)點(diǎn)進(jìn)行更新
self.next = newnext
上面我們就把一個(gè)節(jié)點(diǎn)建立起來(lái)了,那如何把節(jié)點(diǎn)連接起來(lái)呢。
無(wú)序表的鏈表實(shí)現(xiàn)
操作舉例
1. 添加數(shù)據(jù)項(xiàng)add
通過(guò)之前的方式建立了一個(gè)節(jié)點(diǎn),如果初始化它我們知道他是一個(gè)在開(kāi)頭的節(jié)點(diǎn),后面是None.由于無(wú)序表是從表頭開(kāi)始逐個(gè)向后查找,新數(shù)據(jù)所以插入到表頭是我們的最佳選擇。
def add(self,item):
temp = Node(item) #新的要插入的數(shù)據(jù)初始化為一個(gè)節(jié)點(diǎn)
temp.setNext(self.head)#但當(dāng)前節(jié)點(diǎn)的下一個(gè)指向?yàn)橹版湵淼念^部
self.head = temp#把插入的節(jié)點(diǎn)設(shè)為新鏈表的頭部
2. size()的實(shí)現(xiàn) 和 search()的實(shí)現(xiàn)
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
沒(méi)什么可說(shuō)的,設(shè)置一個(gè)計(jì)數(shù)器,然后遍歷元素。
3. remove(item)實(shí)現(xiàn)
我們需要先用類(lèi)似search的方法找到元素,然后它指向的后一個(gè)元素和前一個(gè)元素怎么連在一起呢?
這時(shí)就需要維護(hù)前一個(gè)節(jié)點(diǎn)的引用。
def remove(self,item):
current = self.head
previous = None
found = False
while not found:
if current.getData() == item:
found = True
else:
previous = current#不斷地往后找,然后把當(dāng)前的節(jié)點(diǎn)記作前一個(gè)結(jié)點(diǎn),這樣在找到后就可以對(duì)前一個(gè)結(jié)點(diǎn)進(jìn)行操作。
current = current.getNext()
if previous == None:
self.head = current.getNext()
else:
previous.setNext(current.getNext())
好了那下面我們來(lái)看無(wú)序表的完整實(shí)現(xiàn)
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 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())
mylist = UnorderedList()
mylist.add(31)
mylist.add(77)
mylist.add(17)
mylist.add(93)
mylist.add(26)
mylist.add(54)
print(mylist.length())
print(mylist.search(93))
print(mylist.search(100))
mylist.add(100)
print(mylist.search(100))
print(mylist.length())
mylist.remove(54)
print(mylist.length())
mylist.remove(93)
print(mylist.length())
mylist.remove(31)
print(mylist.length())
print(mylist.search(93))
有序鏈表
概述
之前無(wú)序鏈表時(shí)我們就能推測(cè)出有序的意思,也就是排列過(guò)大小的唄~
有序表依據(jù)數(shù)據(jù)項(xiàng)的可比性質(zhì)(如整數(shù)大小,字母表前后)來(lái)決定數(shù)據(jù)項(xiàng)在列表中的位置。
比如下面我們要實(shí)現(xiàn)越小的越靠近列表頭的操作。
有序表中的操作:
OrderedList():創(chuàng)建一個(gè)新的空有序列表。它返回一個(gè)空有序列表并且不需要傳遞任何參數(shù)。
add(item):在保持原有順序的情況下向列表中添加一個(gè)新的元素,新的元素作為參數(shù)傳遞進(jìn)函數(shù)而函數(shù)無(wú)返回值。假設(shè)列表中原先并不存在這個(gè)元素。
remove(item):從列表中刪除某個(gè)元素。欲刪除的元素作為參數(shù),并且會(huì)修改原列表。假設(shè)原列表
中存在欲刪除的元素。
search(item):在列表中搜索某個(gè)元素,被搜索元素作為參數(shù),返回一個(gè)布爾值。
isEmpty():測(cè)試列表是否為空,不需要輸入?yún)?shù)并且其返回一個(gè)布爾值。
size():返回列表中元素的數(shù)量。不需要參數(shù),返回一個(gè)整數(shù)。
index(item):返回元素在列表中的位置。需要被搜索的元素作為參數(shù)輸入,返回此元素的索引值。假設(shè)這個(gè)元素在列表中。
pop():刪除并返回列表中的最后一項(xiàng)。不需要參數(shù),返回刪除的元素。假設(shè)列表中至少有一個(gè)元素。
pop(pos):刪除并返回索引 pos 指定項(xiàng)。需要被刪除元素的索引值作為參數(shù),并且返回這個(gè)元素。假設(shè)該元素在列表中。
有序鏈表的實(shí)現(xiàn)
其實(shí)大部分操作都和無(wú)序表相同
search()方法
在無(wú)序表中如果不存在,搜索的時(shí)候會(huì)遍歷整個(gè)表。
但是在有序表中,因?yàn)橛许樞?#xff0c;一旦當(dāng)前節(jié)點(diǎn)大于要查找的數(shù)據(jù),就直接宣判死刑可以返回False了。
def search(self,item):
current = self.head
found = False
stop = False# 加入了一個(gè)stop可以直接停住
while current != None and not found and not stop:#這里有三個(gè)條件
if current.getData() == item:
found = True
else:
if current.getData() > item:
stop = True
else:
current = current.getNext()
return found
add()方法
和無(wú)序表相比,改動(dòng)最大的方法是 add。回想一下在無(wú)序列表中的 add 方法,只需要在原列表頭加一個(gè)新的節(jié)點(diǎn)。然而在有序表里我們要找到大小合適的位置才行。
所以我們還是要定位一個(gè)previous(前一個(gè)元素)。
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)
有序表的完整實(shí)現(xiàn)如下:
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 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)
def isEmpty(self):
return self.head == None
def length(self):
current = self.head
count = 0
while current != None:
count = count + 1
current = current.getNext()
return count
def traverse(self):
current = self.head
while current != None:
print(current.getData())
current = current.getNext()
mylist = OrderedList()
mylist.add(31)
mylist.add(77)
mylist.add(17)
mylist.add(93)
mylist.add(26)
mylist.add(54)
print(mylist.length())
print(mylist.search(93))
print(mylist.search(100))
mylist.traverse()
總結(jié)分析
當(dāng)分析鏈表方法的復(fù)雜度時(shí),我們應(yīng)該考慮它們是否需要遍歷鏈表。考慮一個(gè)有 n 個(gè)節(jié)點(diǎn)的鏈表,isEmpty 方法復(fù)雜度是 O(1),因?yàn)樗恍枰獧z查鏈表的頭指針是否為 None。對(duì)于方法 size,則總需要 n 個(gè)步驟,因?yàn)槌吮闅v整個(gè)鏈表以外,沒(méi)有辦法知道鏈表的節(jié)點(diǎn)數(shù)。因此,size 方法的復(fù)雜度是 O(n)。無(wú)序列表的 add 方法的復(fù)雜度是 O(1),因?yàn)槲覀冇肋h(yuǎn)只需要在鏈表的頭部簡(jiǎn)單地添加一個(gè)新的節(jié)點(diǎn)。但是,search、remove 和在有序列表中的 add 方法,需要遍歷。盡管在平均情況下,它們可能只需要遍歷一半的節(jié)點(diǎn),但這些方法的復(fù)雜度都是 O(n),因?yàn)樵谧钤愀獾那闆r下需要遍歷整個(gè)鏈表。
參考資料:MOOC配套教材及代碼
《Python數(shù)據(jù)結(jié)構(gòu)與算法分析》 第2版
總結(jié)
以上是生活随笔為你收集整理的python有序列表无序列表区别_用Python链表实现有序表与无序表的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Mysql 导入3亿数据
- 下一篇: 2组语法,1个函数,教你学会用Pytho