8.基本数据结构-顺序表和链表
一.內存
- 計算機的作用:對數據進行存儲和運算。首先我們需要知道我們目前使用的計算機都是二進制的計算機,就以為著計算機只可以存儲和運算二進制的數據。例如下載好的一部電影,該電影可以存儲到計算機中,計算機中存儲的是基于二進制的電影數據,然后我們可以通過相關的視頻播放軟件結合相關的硬件對電影的二進制數據進行相關的運算操作,所產生的結果就是我們可以看到電影的畫面和聽到音頻的聲音。
- 問題:闡述計算機如何計算1+2的結果?
- 闡述:簡單理解為,首先可以將1和2輸入到計算機中,然后計算機會將1和2轉換成二進制的數據進行數據存儲,然后通過加法器進行兩個二進制數值的計算并返回結果。
- 分析:上述的闡述中提到,計算機首先需要存儲1和2這兩個數值,那么計算機如何進行數據的存儲呢?那么毫無疑問,計算機可以將數據直接存儲到內存中。
- 變量:我們在編程世界中,可以將某個數值直接賦值給一個變量,但是最終數值會被存儲到計算機的內存中,因此我們可以理解為,變量表示的就是計算機中進行數據存儲的某一塊內存。
- 如何形象化的理解計算機的內存?
- 舉例:將計算機的內存空間映射到我們現實生活中的話,內存就好比是我們在現實生活中三維立體的空間。生活在北京的北漂們,幾乎都居住的是一個獨立的公寓或者合租在一個幾居室的某一個房間中,那么北漂甲就好比是數據,而他所居住的房間則就是存儲數據的一塊內存空間。
- 分析:從上述案例中,我們可以得知北漂甲居住的房間會有兩個基本的屬性,其一就是房間空間的大小,其二就是房間的一個位置標識(門牌號)。那么計算機中存儲數據的內存空間也會有這兩個最基本的屬性:內存空間大小和內存空間的地址。內存空間的大小可以表示該空間可以存儲數據值的大小范圍,內存空間的地址(用十六進制數值表示)可以用來通過尋址定位、查找到該內存空間中所存儲的數據值。
- 如何理解 a = 10 這條賦值語句對應的內存圖呢?
- 引用:當一個變量中存儲的是某一塊內存空間的地址,則該變量即可成為那塊內存空間的引用。a=10,a就是10所在內存空間的一個引用。
- 指向:當一個變量中存儲了一塊內存空間的地址,則稱該變量(引用)指向了那塊內存。
- 不同類型數據占用內存空間的大小:整形(4字節),浮點型(8字節),字符型(1字節)
二.順序表:集合中存儲的元素是有順序的。順序表的結構可以分為兩種形式:單數據類型和多數據類型。
- 單數據類型:在內存中如何存儲 int a = 10,20,30,如何取得每一個數據值呢?
- 多數據類型:在內存中如何存儲 li = 10,'a',96.5,如何獲取每一個數據值呢?
? - 順序表的弊端:順序表的結構需要預先知道數據大小來申請連續的存儲空間,而在進行擴充時又需要進行數據的搬遷。
-?Python中的?list?和?tuple?兩種類型采用了順序表的實現技術。
三.鏈表:相對于順序表,鏈表結構可以充分利用計算機內存空間,實現靈活的內存動態管理。
-?鏈表(Linked list)是一種常見的基礎數據結構,是一種線性表,但是不像順序表一樣連續存儲數據,而是每一個結點(數據存儲單元)里存放下一個結點的信息(即地址):
-?1、單向鏈表
單向鏈表也叫單鏈表,是表中最簡單的一種形式,它的每個節點包含兩個域,一個信息域(元素域)和一個鏈接域。這個鏈接指向鏈表中的下一個節點,而最后一個節點的鏈接域則指向一個空值。
-?表中元素elem用來存放具體的數據。
- 鏈接域next用來存放下一個節點的位置。
- 變量p指向鏈表的頭節點(首節點)的位置,從p出發能找到表中的任意節點。
- 單向鏈表的抽象數據類型定義:
.?is_empty():鏈表是否為空
. length():鏈表長度
. travel():遍歷整個鏈表
. add(item):鏈表頭部添加元素
. append(item):鏈表尾部添加元素
. insert(pos, item):指定位置添加元素
. remove(item):刪除節點
. search(item):查找節點是否存在
- 代碼實現:
class Node():def __init__(self,item):self.item = itemself.next = Nonedef __str__(self):return str(self.item) class Link():def __init__(self):#永遠指向鏈表中第一個節點self._head = Nonedef isEmpty(self):return self._head is Nonedef add(self,item):node = Node(item)node.next = self._headself._head = nodedef length(self):count = 0if self.isEmpty():return countelse:cur = self._headwhile cur is not None:count += 1cur = cur.nextreturn countdef travel(self):cur = self._headwhile cur is not None:print(cur)cur = cur.nextdef append(self,item):node = Node(item)cur = self._headif self.isEmpty():self._head = nodeelse:while cur is not None:#因為循環遍歷結束后cur會指向空并非最后一個節點pre_cur = curcur = cur.nextpre_cur.next = nodedef search(self,item):ex = Falsecur = self._headwhile cur is not None:if cur.item == item:ex = Truebreakcur = cur.nextreturn exdef insertTo(self,item,index):cur = self._headex = 0node = Node(item)#插入到第一個節點位置if index <= 0:self.add(item)#插入到最后一個節點位置elif index >= self.length():self.append(item)else:while cur is not None:pre = cur cur = cur.next#此處插入的一定不是第一個節點和最后一個節點位置,因此index要減1if ex == index-1:node.next = curpre.next = nodebreakex += 1def remove(self,item):pre = Nonecur = self._head#刪除的是第一個節點if cur.item == item:self._head = cur.nextelse:while cur is not None:pre = curcur = cur.nextif cur.item == item:pre.next = cur.nextcur.next = Nonecur = cur.next#測試代碼 link = Link() link.add('bobo') link.add('jay') link.add('tom') link.add('jerry') # print(link.search('tom')) # link.insertTo('haha',1) link.remove('bobo') link.travel()
?
- 2.單向循環鏈表:單鏈表的一個變形是單向循環鏈表,鏈表中最后一個節點的next域不再為None,而是指向鏈表的頭結點。
-?基本操作和單鏈表基本一樣,實現代碼如下:
# coding=utf-8 # 單向循環鏈表class Node:"""節點"""def __init__(self, item):self.item = itemself.next = Nonedef __str__(self):return str(self.item)class SinCycLinkedList:"""單向循環鏈表"""def __init__(self):self._head = Nonedef is_empty(self):"""判斷鏈表是否為空"""return self._head is Nonedef length(self):"""鏈表長度"""if self.is_empty():return 0count = 1cur = self._headwhile cur.next != self._head:# print("cur", cur.item)count += 1cur = cur.nextreturn countdef travel(self):"""遍歷"""if self.is_empty():returncur = self._headprint(cur.item)while cur.next != self._head:cur = cur.nextprint(cur.item)def add(self, item):"""在頭部添加一個節點"""node = Node(item)if self.is_empty():self._head = nodenode.next = self._headelse:node.next = self._headcur = self._headwhile cur.next != self._head:cur = cur.nextcur.next = nodeself._head = nodedef append(self, item):"""在尾部添加一個節點"""node = Node(item)if self.is_empty():self._head = nodenode.next = self._headelse:cur = self._head# print(type(cur), cur.item, cur.next)while cur.next != self._head:cur = cur.next# print(cur.item)cur.next = nodenode.next = self._headdef insert(self, pos, item):"""指定位置pos添加節點"""if pos <= 0:self.add(item)elif pos > (self.length() - 1):self.append(item)else:node = Node(item)cur = self._headcur_pos = 0while cur.next != self._head:if (pos - 1) == cur_pos:node.next = cur.nextcur.next = nodebreakcur_pos += 1cur = cur.nextdef remove(self, item):"""刪除一個節點"""if self.is_empty():returnpre = self._head# 刪除首節點if pre.item == item:cur = prewhile cur.next != self._head:cur = cur.nextcur.next = pre.next # 刪除首節點(跳過該節點)self._head = pre.next # 重新指定首節點# 刪除其他的節點else:cur = prewhile cur.next != self._head:if cur.next.item == item:cur.next = cur.next.nextcur = cur.nextdef search(self, item):"""查找節點是否存在"""if self.is_empty():return -1cur_pos = 0cur = self._headif cur.item == item:return cur_poswhile cur.next != self._head:if cur.item == item:return cur_poscur_pos += 1cur = cur.nextif cur_pos == self.length() - 1:return -1if __name__ == "__main__":ll = SinCycLinkedList()ll.add(1) # 1ll.add(2) # 2 1# ll.travel()ll.append(3) # 2 1 3ll.insert(2, 4) # 2 1 4 3ll.insert(4, 5) # 2 1 4 3 5ll.insert(0, 6) # 6 2 1 4 3 5print("length:", ll.length()) # 6ll.travel() # 6 2 1 4 3 5print("search(3)", ll.search(3)) # 4print("search(7)", ll.search(7)) # -1print("search(6)", ll.search(6)) # 0print("remove(1)")ll.remove(1)print("length:", ll.length()) # 6 2 4 3 5print("remove(6)")ll.remove(6)ll.travel()3.雙向鏈表:一種更復雜的鏈表是 "雙向鏈表" 或 "雙面鏈表"。每個節點有兩個鏈接:一個指向前一個節點,當次節點為第一個節點時,指向空值;而另一個指向下一個節點,當此節點為最后一個節點時,指向空值。
- 代碼實現:
# coding=utf-8 # 雙向鏈表class Node:"""節點"""def __init__(self, item):self.item = itemself.prev = Noneself.next = Noneclass DLinkList:"""雙向鏈表"""def __init__(self):self._head = Nonedef is_empty(self):"""判斷鏈表是否為空"""return self._head is Nonedef length(self):"""獲取鏈表長度"""if self.is_empty():return 0else:cur = self._headcount = 1while cur.next is not None:count += 1cur = cur.nextreturn countdef travel(self):"""遍歷鏈表"""print("↓↓" * 10)if self.is_empty():print("")else:cur = self._headprint(cur.item)while cur.next is not None:cur = cur.nextprint(cur.item)print("↑↑" * 10)def add(self, item):"""鏈表頭部添加節點"""node = Node(item)if self.is_empty():self._head = nodeelse:cur = self._headnode.next = curcur.prev = nodeself._head = nodedef append(self, item):"""鏈表尾部添加節點"""node = Node(item)if self.is_empty():self._head = nodeelse:cur = self._head# 遍歷找到最后一個節點while cur.next is not None:cur = cur.next# 在尾節點添加新的節點cur.next = nodenode.prev = curdef insert(self, pos, item):"""指定位置添加"""# 頭部添加if pos <= 0:self.add(item)# 尾部添加elif pos > (self.length() - 1):self.append(item)# 其他位置添加else:node = Node(item)cur = self._headcur_pos = 0while cur.next is not None:if cur_pos == (pos - 1):# 與下一個節點互相指向node.next = cur.nextcur.next.prev = node# 與上一個節點互相指向cur.next = nodenode.prev = curcur_pos += 1cur = cur.nextdef remove(self, item):"""刪除節點"""if self.is_empty():returnelse:cur = self._head# 刪除首節點if cur.item == item:self._head = cur.nextcur.next.prev = None# 刪除其他節點else:while cur.next is not None:if cur.item == item:# 刪除之前:1 ←→ [2] ←→ 3# 刪除之后:1 ←→ 3cur.prev.next = cur.nextcur.next.prev = cur.prevcur = cur.next# 刪除尾節點if cur.item == item:cur.prev.next = Nonedef search(self, item):"""查找節點是否存在"""if self.is_empty():return -1else:cur = self._headcur_pos = 0while cur.next is not None:if cur.item == item:return cur_poscur_pos += 1cur = cur.nextif cur_pos == (self.length() - 1):return -1if __name__ == "__main__":ll = DLinkList()ll.add(1) # 1ll.add(2) # 2 1ll.append(3) # 2 1 3ll.insert(2, 4) # 2 1 4 3ll.insert(4, 5) # 2 1 4 3 5ll.insert(0, 6) # 6 2 1 4 3 5print("length:", ll.length()) # 6ll.travel() # 6 2 1 4 3 5print("search(3)", ll.search(3))print("search(4)", ll.search(4))print("search(10)", ll.search(10))ll.remove(1)print("length:", ll.length())ll.travel()print("刪除首節點 remove(6):")ll.remove(6)ll.travel()print("刪除尾節點 remove(5):")ll.remove(5)ll.travel()?
轉載于:https://www.cnblogs.com/bobo-zhang/p/10529330.html
總結
以上是生活随笔為你收集整理的8.基本数据结构-顺序表和链表的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 360借条正规吗,合法吗?
- 下一篇: Hadoop配置文件参数详解