顺序表与链表
内存
-
计算机的作用
- 存储和运算二进制数据
-
计算机如何实现1+1=?的操作
- 将1加载到内存中,然后基于计算机的加法寄存器对指定内存中存储的数据进行加法运算。
-
变量
- 本质讲,变量指的就是计算机中的某一块内存空间
- 内存空间有两个固有属性
- 地址
- 使用16进制数表示
- 作用:方便cpu寻址(门牌号)
- 大小
- bit,byte,kb,mb,gb,tb
- 决定该块内存存储的数值的范围
- 相同类型的数据,开辟固有大小的内存空间
- 整形数据:4byte
- 浮点型:4byte(单精度),8byte(双精度)
- 字符型:1byte
- 地址
-
引用和指向
- 引用:就是变量。通常讲,变量表示的就是一块内存空间的地址。
- 指向:如果一个变量或引用存储和表示了一块内存空间的地址,则该变量或引用指向了该块内存空间。
顺序表
-
概念
- 将元素顺序地存放在一块连续的存储区里,元素间的顺序关系由它们的存储顺序自然表示。
-
顺序表的结构可以分为两种形式:
- 单数据类型(如数组)
- 数据元素本身连续存储,每个元素所占的存储单元大小固定相同,元素的下标是其逻辑地址,而元素存储的物理地址(实际内存地址)可以通过存储区的起始地址Loc (e0)加上逻辑地址(第i个元素)与存储单元大小(c)的乘积计算而得,即:Loc(ei) = Loc(e0) + c*i
- 故,访问指定元素时无需从头遍历,通过计算便可获得对应地址,其时间复杂度为O(1)。
- 多数据类型(如元组和列表)
- 元素的大小不统一,则需要采用元素外置的形式,将实际数据元素另行存储,而顺序表中各单元位置保存对应元素的地址信息(即链接)。由于每个链接所需的存储量相同,这个量通常很小,顺着链接找到实际存储的数据元素
- 这样的顺序表也被称为对实际数据的索引,这是最简单的索引结构。
- 单数据类型(如数组)
-
弊端
- 顺序表的构建需要预先知道数据大小来申请连续的存储空间,而在进行扩充时又需要进行数据的搬迁,所以使用起来并不是很灵活。
链表
-
定义
- 链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是不像顺序表一样连续存储数据,而是在每一个节点(数据存储单元)里存放下一个节点的位置信息(即地址)
-
优点
- 链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。
-
单向链表
- 单向链表也叫单链表,是链表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。
-
单链表操作
- is_empty() :链表是否为空
- length() :链表长度
- travel() :遍历整个链表
- add(item) :链表头部添加元素
- append(item) :链表尾部添加元素
- insert(pos, item) :指定位置添加元素
- remove(item) :删除节点
- search(item) :查找节点是否存在
-
单链表实现:
# coding:utf-8 class Node: '''单链表的节点''' def __init__(self,item): self.item = item self.next = None class Link_list: def __init__(self): self._head = None def is_empty(self): '''判空''' return self._head == None def add(self,item): '''头部添加''' node = Node(item) node.next = self._head self._head = node def append(self,item): '''尾部添加''' node = Node(item) #先判空,若为空链表,则_head指向新节点 if self.is_empty(): self._head = node #不为空,则找到尾节点,然后尾节点的next指向新节点 else: cur = self._head while cur.next: cur = cur.next cur.next = node def length(self): '''链表长度''' if self.is_empty(): return 0 count = 1 cur = self._head while cur.next: count += 1 cur = cur.next return count def travel(self): '''遍历''' cur = self._head while cur: print(cur.item) cur = cur.next def search(self,item): '''查找节点是否存在''' cur = self._head while cur: if cur.item == item: return True cur = cur.next return False def insert(self,pos,item): '''指定位置插入节点''' node = Node(item) #判断插入位置,如果为0,则从头部插入 if pos == 0: self.add(node) return #其它位置,需要找到插入点前面一个节点pre和后面一个节点cur pre = None cur = self._head for i in range(pos): pre = cur cur = cur.next pre.next = node node.next = cur def remove(self,item): '''删除节点''' pre = None cur = self._head while cur: if cur.item == item: if not pre: self._head = cur.next else: pre.next = cur.next break pre = cur cur = cur.next if __name__ == '__main__': link = Link_list() print(link.is_empty()) link.add(1) print(link.is_empty()) link.add(2) link.append(3) link.insert(1,2.5) print(link.search(4)) link.travel()
-
实现单链表倒置
def reverse(self): '''链表倒置''' pre = None #前一个节点 cur = self._head #当前节点 post = cur.next #后一个节点 while post: #每循环一次,就修改当前节点的next指向前一个节点,然后每个节点后移一位 #循环退出时,cur指向最后一个节点 cur.next = pre pre = cur cur = post post = post.next #修改最后一个节点next指向前一个节点 cur.next = pre #修改_head指向最后一个节点 self._head = cur