赞
踩
数据在内存中顺序存储,可以通过下标索引。
特点:支持随机访问,索引元素效率高,插入元素和删除元素效率低。
数组存放空间连续,插入元素时需要将插入位置及后面的元素一次往后移动一位,然后将元素插入到空出的插入位置。
python中的list是一个动态数组,支持动态扩容(2^n),list中封装了数组常用的方法:
- >>> list = [3, 5, 7]
- >>> list.append(9) # 往数组尾部添加元素
- >>> list
- [3, 5, 7, 9]
- >>> list.insert(2,5) # 在指定位置插入元素
- >>> list
- [3, 5, 5, 7, 9]
- >>> list.pop() # 取数组最后一个元素,会从数组中删除该元素
- 9
- >>> list
- [3, 5, 5, 7]
- >>> list.remove(5) # 删除数组中的指定元素,有多个时只删除第一个
- >>> list
- [3, 5, 7]
- >>> list.index(5) # 查找元素在列表中的位置
- 1
- >>> list.reverse() # 列表反转
- >>> list
- [7, 5, 3]
在python中通过id()函数来输出列表元素的第地址时,可以看到id的值并不是连续的,这是为什么呢?
- >>> arr = ['a','b','c']
- >>> for char in arr:
- print(id(char))
- 2204167613216
- 2204167611536
- 2204167474288
因为python的list存的是元素对象的引用而不是元素本身,从下面代码中可以看出来,所以输出的id值是元素对象的引用值,在底层的c语言中是使用数组来实现的。
- >>> a = 1
- >>> id(a)
- 1598830848
- >>> b = [a]
- >>> id(b)
- 9390640
- >>> id(b[0])
- 1598830848
链表数据在内存中的存储不连续,链表有一系列的节点通过指针依次连接起来,每个节点包含数据域和指针域,数据域存储数据,指针域存储下一个节点的指针。
单向链表也叫单链表,是链表中最简单的形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。
因为链表中的数据不是顺序存储的,不能随机访问,因此链表的查询效率低,但是链表在任意位置插入和删除节点时不用移动节点位置,因此插入和删除效率高。
链表实现
通常有以下步骤:
- class Node(object):
- '''1.节点定义'''
-
- def __init__(self,data):
- # 数据域
- self.data = data
- # 指针域,创建时为None
- self.next = None
-
- class SingleList(object):
- '''2.链表定义'''
-
- def __init__(self):
- # 链表头
- self.head = None
-
- if __name__ == '__main__':
- #3.链表使用
- # 创建链表
- singlelist = SingleList()
- # 创建节点
- node1 = Node(3)
- # 将链表头指向节点
- singlelist.head = node1
- # 创建节点往链表上添加
- node2 = Node(5)
- node1.next = node2
- node3 = Node(7)
- node2.next = node3
-
- # 创建临时变量指向头节点
- temp = singlelist.head
- # 取头节点的数据
- print(temp.data)
- # 取下一个节点的数据
- temp = temp.next
- print(temp.data)
输出结果:
3
5
上面定义并使用了一个单项链表,但是链表的使用很不方便,获取元素添加和获取需要定位到节点,长度也没法知道,所以需要定义一些常用的方法,方便链表的使用。
链表中的常用方法:
- class Node(object):
- '''节点定义'''
-
- def __init__(self,data):
- # 数据域
- self.data = data
- # 指针域,创建时为None
- self.next = None
-
- class SingleList(object):
- '''链表定义'''
-
- def __init__(self):
- # 链表头
- self.head = None
-
- def is_empty(self):
- '''链表判空'''
- return self.head is None
-
- def length(self):
- '''链表长度'''
- # 获取初始的头指针
- cur = self.head
- count = 0
- while cur is not None:
- count += 1
- # 指针后移1位
- cur = cur.next
- return count
-
- def datas(self):
- '''链表遍历'''
- cur = self.head
- while cur is not None:
- # 返回生成器
- yield cur.data
- # 指针后移1位
- cur = cur.next
-
- def add(self,data):
- '''在头部插入节点'''
- # 创建新节点
- node = Node(data)
- # 新节点指向原头节点
- node.next = self.head
- # 头节点指向新节点
- self.head = node
-
- def append(self,data):
- '''向尾部插入节点'''
- node = Node(data)
- if self.is_empty():
- # 空链表则直接将head指向node
- self.head = node
- else:
- cur = self.head
- while cur.next is not None:
- # 将指针移到最后一个节点
- cur = cur.next
- # 将最后一个节点的指针指向node
- cur.next = node
-
- def insert(self,index,data):
- '''任意位置插入节点'''
- if index <= 0:
- # 在头部插入
- self.add(data)
- elif index >= self.length():
- # 在尾部插入
- self.append(data)
- else:
- cur = self.head
- for i in range(index - 1):
- cur = cur.next
- # 创建新节点
- node = Node(data)
- # 将新节点指向就节点
- node.next = cur.next
- # 将旧节点前一个节点指向新节点
- cur.next = node
-
- def remove(self, item):
- """ 删除一个结点 """
- if self.is_empty():
- return
- cur = self.head
- pre = None
- # 第一个元素为需要删除的元素
- if cur.data == item:
- if cur.next != None:
- cur.next = self.head.next
- # 调整头部结点
- self.head = self.head.next
- else:
- # 只有一个元素
- self.head = None
- else:
- # 不是第一个元素
- pre = self.head
- while cur.next != self.head:
- if cur.data == item:
- # 删除
- pre.next = cur.next
- return True
- else:
- pre = cur # 记录前一个指针
- cur = cur.next # 调整指针位置
- # 当删除元素在末尾
- if cur.data == item:
- pre.next = self.head
- return True
-
- def find(self, data):
- """ 查找元素是否存在"""
- return data in self.datas()
-
- def printlist(self):
- '''打印链表元素'''
- print('当前链表:')
- for i in self.datas():
- print(i)
-
- if __name__ == '__main__':
- # 创建链表
- singlelist = SingleList()
-
- #添加节点
- singlelist.add(3)
- singlelist.append(5)
- singlelist.append(7)
- # 链表长度
- length = singlelist.length()
- print('链表长度:',length)
-
- singlelist.printlist()
-
- # 删除元素
- singlelist.remove(5)
- print('--删除元素--')
- singlelist.printlist()
-
- # 任意位置插入元素
- singlelist.insert(2,666)
- print('--任意位置插入元素--')
- singlelist.printlist()
双向链表与与单向链表的区别在于,双向链表的节点包含了两个指针域,如下图,prev指针域指向前一个节点,next指向后一个节点,head指向头节点,第一个节点的prev指针为None,最后一个节点的next为空。
为了方便操作双向链表,也会在链表中定义一些常用的方法。实例如下:
- class Node(object):
- '''双链表的节点'''
-
- def __init__(self,data):
- self.data = data
- self.prev = None
- self.next = None
-
- class DoubleLinkedList(object):
- '''双向链表'''
-
- def __init__(self):
- self.head = None
- self.tail = None
-
- def is_empty(self):
- return self.head is None
-
- def length(self):
- cur = self.head
- count = 0
- while cur is not None:
- cur = cur.next
- count += 1
- return count
-
- def items(self):
- '''顺序遍历'''
- cur = self.head
- while cur is not None:
- yield cur.data
- cur = cur.next
-
- def add(self,data):
- '''向链表头部添加节点'''
- node = Node(data)
- if self.head is None:
- self.head = node
- self.tail = node
- else:
- node.next = self.head
- self.head.prev = node
- self.head = node
-
- def append(self,data):
- '''向链表尾部添加节点'''
- node = Node(data)
- if self.tail is None:
- self.head = node
- self.tail = node
- else:
- node.prev = self.tail
- self.tail.next = node
- self.tail = node
-
- def insert(self,index,data):
- '''向指定位置添加节点'''
- if index <= 0:
- self.add(data)
- elif index >= self.length():
- self.append(data)
- else:
- node = Node(data)
- cur = self.head
- for i in range(index):
- cur = cur.next
- # 循环完后cur指向节点index了
- node.next = cur
- node.prev = cur.prev
- cur.prev.next = node
- cur.prev = node
-
- def remove(self, item):
- """ 删除一个结点 """
- if self.is_empty():
- return
- # 当删除的节点在尾部
- if item == self.tail.data:
- self.tail = self.tail.prev
- self.tail.next = None
- return True
- cur = self.head
- pre = None
- # 第一个节点为需要删除的节点
- if cur.data == item:
- # 有多个节点
- if cur.next != None:
- self.head = cur.next
- return True
- # 只有一个节点
- else:
- self.head = None
- return True
- else:
- # 首尾之外的任意节点
- while cur.next != self.tail:
- if cur.data == item:
- pre.next = cur.next
- cur.next.prev = pre
- return True
- else:
- pre = cur
- cur = cur.next
-
- def find(self, data):
- """ 查找节点是否存在"""
- return data in self.items()
-
- def print_list(self):
- '''打印链表数据'''
- print('链表当前节点:')
- for node in self.items():
- print(node)
-
- if __name__ == '__main__':
- # 实例化双向链表
- doublelist = DoubleLinkedList()
-
- # 向头部添加节点
- doublelist.add(10)
- doublelist.add(20)
- doublelist.print_list()
-
- # 向尾部添加节点
- doublelist.append(30)
- doublelist.append(40)
- doublelist.print_list()
-
- # 任意位置添加节点
- doublelist.insert(2,666)
- doublelist.print_list()
-
- # 删除首尾和任意节点
- doublelist.remove(666)
- doublelist.remove(20)
- doublelist.remove(40)
- doublelist.print_list()
输出结果:
链表当前节点:
20
10
链表当前节点:
20
10
30
40
链表当前节点:
20
10
666
30
40
链表当前节点:
10
30
其他数据结构:栈、队列、树等的实现可以看:python-data-structure
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。