程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

數據結構與算法之線性表的概念(python3)

編輯:Python

提示:文章寫完後,目錄可以自動生成,如何生成可參考右邊的幫助文檔

文章目錄

  • 前言
  • 3、線性表概念和抽象數據類型?
    • 3.2順序表
      • 3.2.1元素外置順序表
      • 3.2.2順序表的結構定義
      • 3.2.3順序表的兩種形式
      • 3.2.4 動態順序表
      • 3.2.5 順序表的特點
    • 3.3鏈表
      • 1 特點:
      • 2 節點結構
      • python實現鏈表-單鏈表的插入和刪除節點
      • 3.5.1 雙鏈表的定義和描述
      • 雙鏈表的插入和刪除節點
  • 總結


前言

提示:這裡可以添加本文要記錄的大概內容:


提示:以下是本篇文章正文內容,下面案例可供參考

3、線性表概念和抽象數據類型?

線性表有兩種存儲方式:順序表和鏈表

1定義:
線性表是相同數據類型的n個元素的有限序列.數據元素類型相同
2結構特點:
第一個元素只有後繼沒有前驅;
最後一個元素只有前驅沒有後繼,
其他元素只有唯一一個前驅和唯一一個後繼

3.2順序表

定義:線性表的順序存儲

1 什麼是內存
存儲器: 外存,內存
外存: c盤,d盤 u盤 長期保持,存取速度慢
內存: 存取速度快
cpu: 只能直接訪問內存,在內存中取數據進行該操作

注意:順序表不適合用來存儲頻繁用來插入和刪除的數據

2 python 中順序表的實現

python中list和tuple兩種類型采用了順序表的實現技術;python中list和tuple底層是基於數組的;

3.2.1元素外置順序表

不同類型的元素不能存放在基本的順序表中;基本的順序表要求元素的類型必須是相同的;

若我們非要將不同類型的數據放到順序表,我們可以使用順序表來存放各個元素的地址,這種叫元素外置的順序表,對於元素外置的順序表使用插入,刪除等是通過對元素地址操作來實現的

3.2.2順序表的結構定義

一個順序表的完整信息包括兩部分:
1 數據區:表中的元素集合
2 表頭: 記錄表的整體情況的信息,元素存儲區的容量;已有元素個數兩項;

3.2.3順序表的兩種形式

a 一體式結構,存儲表信息的單元與元素存儲區以連續的方式安排在一塊存儲區裡,兩部分數據的整體形成一個完整的順序表對象

b 分離式結構,表對象只保存整個表有關的信息(容量和元素個數),實際數據元素存放在另一個獨立元素存儲區裡,通過鏈接與基本表對象關聯

這兩種結構如何選取?

若我們的數據經常擴容,我們就使用分離式動態表;若我們數據不經常改變就使用一體式順序表,便於管理;

3.2.4 動態順序表

動態順序表: 當你執行添加數據操作時,python中的列表自動的去擴容,即換一塊更大的存儲區域,這就是所謂的動態順序表
列表就是動態順序表,采用的是分離式結構.
而且列表是元素外置的順序表

3.2.5 順序表的特點

優點:
邏輯相鄰,物理相鄰: 存儲空間使用緊湊,不必為節點間的邏輯關系而增加額外的存儲開銷
可隨機存儲任意元素 O(1)
python 列表也引用的是數組結構

缺點:
插入,刪除操作需要移動大約表中一半的元素,對n大的順序表效率低

3.3鏈表

1 特點:

用一組任意的存儲單元(可連續,可不連續)存儲線性表的數據元素

順序表呢,是物理上先後關系體現邏輯上先後關系;
鏈表是不連續的如何體現數據之間的線性關系呢?
答:每個數據元素ai,除了存儲本省信息外,還需要存儲其直接後繼或者直接前驅的信息,即利用地址(指針)實現了用不相鄰的存儲單元存放邏輯上相鄰的元素

2 節點結構

1數據域: 數據元素本身信息

2鏈接域(地址域,指針域): 直接後繼或直接前驅的存儲地址

3 線性鏈表的分類:
1 單鏈表: 每個結點除包含數據域外,只設置一個鏈接域,用於指向其後繼結點

2 雙向鏈表: 每個結點除包含數據域外,設置兩個鏈接域,分別用以指向其前驅結點和後繼結點.

# 單鏈表類定義

4 掃描指針和遍歷單鏈表
單鏈表的特點是每個結點只保存其直接後繼的地址,在已知單鏈表的head首地址的情況下,如果要訪問到單鏈表中的所有結點,需要一個掃描指針(掃描游標)

python實現鏈表-單鏈表的插入和刪除節點

https://www.bilibili.com/video/BV1Aa4y1E75k?p=12&spm_id_from=pageDriver&vd_source=f0e2d9965dd28bc650e022a3c8d84457


class Node(object):
def __init__(self, data):
self.data = data
self.next = None
class List(object):
def __init__(self):
self.__head = None
def is_empty(self):
if self.__head is None:
return 1
else:
return 0
def add(self, item): # 頭插入法插入元素
s = Node(item) # 生成一個帶插入節點的對象
s.next = self.__head # 修改鏈接
self.__head = s # 修改鏈接
def travel(self): # 遍歷單鏈表,並打印輸出
# 對鏈表中的n個元素掃描一遍,時間復雜度為O(n)
p = self.__head # 定義指針p p從表頭開始
while p is not None: # 判斷指針是否指向了鏈表末尾
print(p.data, end=" ") # 打印p指向的結點數據
p = p.next # 指針下移到下一個元素
def length(self):
count = 0
p = self.__head
while p is not None:
p = p.next
count += 1
return count
def searchpos(self, pos): # 按序號查找, pos是待查找的位置
# 性能分析:與pos取值有關,平均時間復雜度O(n)
len1 = self.length()
if pos > len1:
return
p = self.__head
count = 1
if pos == 0:
return None
else:
while p is not None and count != pos:
p = p.next
count += 1
print(p.data)
return p
pass
def search(self, item): # 按值查找
# 性能分析: 平均時間復雜度 O(n)
p = self.__head
while p is not None and item != p.data:
p = p.next
if p is not None:
if p.data == item:
print(f"數據找到了 {
p.data}")
elif p is None:
return None
return p
def append(self, x):
# 因為需要移動指針,時間復雜度是 O(n)
p = self.__head # 找到頭結點
n = Node(x) # 實例化新節點
if p is None:
self.__head = n
return
while p.next is not None:
p = p.next
p.next = n
def insert(self, pos, x):
# 時間復雜度為O(n),若按照序號插入,需要先找到位置,按位置
# 僅僅插入操作時間復雜度是O(1)
p = self.__head
count = 1
s = Node(x)
# if pos >= self.length():
# return -1
while p.next is not None and count != pos: # 找到要插入的位置
p = p.next
count += 1
if 0 == pos:
s.next = self.__head
self.__head = s
elif p.next is not None:
s.next = p.next
p.next = s
elif p.next is None:
p.next = s
def remove(self, item): # 按值刪除操作
# 查找操作 時間復雜度是 O(n)
# 刪除操作 時間復雜度是 O(1)
p = self.__head
if item == p.data: # 如果刪除的是一個節點
self.__head = p.next
else:
# while p.next is not None and item != p.data:
# pre = p
# p = p.next
# else:
# pre.next = p.next
while p is not None:
if p.data != item:
pre = p
p = p.next
else:
pre.next = p.next
break
return p
l = List()
# l.add(6)
# l.add(9)
# l.add(11)
l.append(6)
l.append(9)
l.append(11)
l.append(13)
l.travel()
print(f"\r\n鏈表的長度為: {
l.length()}")
l.searchpos(2)
l.search(11)
l.insert(0, 44)
l.travel()
print('-------')
l.remove(13)
l.travel()

單鏈表特點:
1 它是一種動態結構, 整個內存空間為多個鏈表公用

2 不需要預先分配空間

3 鏈接域占用額外存儲空間

4 不能隨機存取,查找速度慢.

不論查哪一個元素都是從第一個元素開始查找;


3.5.1 雙鏈表的定義和描述

1 每個結點包含兩個鏈接域,一個指向直接前驅(prior),一個指向直接後繼(next)

2雙鏈表由頭指針head唯一確定

3 將雙鏈表中的頭結點和尾結點鏈接起來可以構成循環鏈表,並稱之為雙向鏈表

雙鏈表的插入和刪除節點

https://www.bilibili.com/video/BV1Aa4y1E75k?p=14&spm_id_from=pageDriver&vd_source=f0e2d9965dd28bc650e022a3c8d84457


總結

提示:這裡對文章進行總結:


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved