让各为读者久等了,笔者正在加班加点肝代码,望各位读者见谅。
以下为本节内容。
**
一、数组
**
数组是一种数据结构,它由一组元素组成,这些元素按照线性顺序排列,并且通过索引访问。数组的元素可以是任何数据类型,包括整数、浮点数、字符串等等。数组有很多种不同的实现方式,其中最常见的是固定大小的静态数组和可变大小的动态数组。
Python中的列表(list)就是一种动态数组,它支持插入、删除和获取元素的操作,也支持切片(slice)和迭代(iteration)等高级操作。可以通过下标(index)来访问列表中的元素,下标从0开始,表示第一个元素,依次递增。
常见的基础操作:
创建一个包含5个元素的列表
my_list = [1, 2, 3, 4, 5]
访问第3个元素
print(my_list[2]) # 输出 3
修改第4个元素的值
my_list[3] = 6
在列表末尾添加一个新元素
my_list.append(7)
删除第2个元素
del my_list[1]
获取列表长度
print(len(my_list)) # 输出 5
切片操作
print(my_list[1:3]) # 输出 [3, 6]
需要注意的是,Python的列表实际上是由动态数组和指向元素的指针组成的,因此插入和删除元素时可能需要移动后面的元素,时间复杂度为O(n),在一些需要高效插入和删除操作的场景中,可能需要使用其他数据结构,如链表等。
当我们需要在程序中存储一组数据时,可以使用线性表来实现。线性表是一种逻辑结构,可以用一组连续的内存空间存储相同类型的数据。
数组是一种线性表的实现方式。在数组中,数据元素存储在连续的内存空间中,并按照一定的规律依次存储。我们可以通过下标来访问数组中的元素。由于数据元素的内存空间是连续的,因此数组具有快速随机访问元素的优势。但是,在进行插入、删除等操作时,由于需要移动大量元素,数组的效率较低。
数组(Array)
class Array:
def __init__(self, capacity):
self._capacity = capacity
self._data = [None] * capacity
self._size = 0
def __len__(self):
return self._size
def __getitem__(self, index):
if not 0 <= index < self._size:
raise IndexError("Index out of range")
return self._data[index]
def __setitem__(self, index, value):
if not 0 <= index < self._size:
raise IndexError("Index out of range")
self._data[index] = value
def append(self, value):
if self._size == self._capacity:
self._resize(2 * self._capacity)
self._data[self._size] = value
self._size += 1
def _resize(self, new_capacity):
new_data = [None] * new_capacity
for i in range(self._size):
new_data[i] = self._data[i]
self._data = new_data
self._capacity = new_capacity
上述代码实现了一个简单的数组,包括以下方法:
__init__(self, capacity)
: 构造函数,创建一个指定容量的数组。
__len__(self)
: 获取数组长度。
__getitem__(self, index)
: 获取指定索引的元素。
__setitem__(self, index, value)
: 设置指定索引的元素。
append(self, value)
: 向数组末尾添加一个元素。
_resize(self, new_capacity)
: 数组扩容,将容量增加到指定大小。
在 Python 中,可以使用列表(list)来实现数组的功能。列表是一种有序的、可变的、可以存储任意类型元素的数据结构。
数组操作
创建数组
在Python中,可以使用内置的列表(list)来实现数组的功能。创建一个有 n n n个元素的数组,可以使用以下代码:
arr = [None] * n
其中,None是Python中的空值,表示数组中的元素暂时为空。
访问元素
可以通过下标来访问数组中的元素,下标从0开始,到 n − 1 n-1 n−1结束。例如:
arr = [1, 2, 3, 4, 5]
print(arr[0]) # 输出1
print(arr[2]) # 输出3
修改元素
可以通过下标来修改数组中的元素。例如:
arr = [1, 2, 3, 4, 5]
arr[0] = 10
arr[2] = 30
print(arr) # 输出[10, 2, 30, 4, 5]
插入元素
在数组中插入元素需要将插入位置之后的元素向后移动一位,然后将新元素放入插入位置。例如:
arr = [1, 2, 3, 4, 5]
n = len(arr)
pos = 2 # 插入位置
val = 6 # 插入值
#将插入位置之后的元素向后移动一位
for i in range(n-1, pos-1, -1):
arr[i+1] = arr[i]
# 插入新元素
arr[pos] = val
print(arr) # 输出[1, 2, 6, 3, 4, 5]
删除元素
在数组中删除元素需要将删除位置之后的元素向前移动一位,然后将最后一个元素放入删除位置。例如:
arr = [1, 2, 3, 4, 5]
n = len(arr)
pos = 2 # 删除位置
# 将删除位置之后的元素向前移动一位
for i in range(pos, n-1):
arr[i] = arr[i+1]
# 将最后一个元素放入删除位置
arr[n-1] = None
print(arr) # 输出[1, 2, 4, 5, None]
遍历数组:可以使用 for 循环来遍历数组
for i in arr:
print(i)
# 输出:
# 0
# 10
# 2
# 3
# 4
数组操作:列表提供了丰富的方法来操作数组,例如 append()、insert()、pop()、remove() 等。
在这里插入代码片# 在数组末尾添加一个元素
arr.append(5)
print(arr) # 输出:[0, 10, 2, 3, 4, 5]
# 在数组的第3个位置插入一个元素
arr.insert(2, 20)
print(arr) # 输出:[0, 10, 20, 2, 3, 4, 5]
# 删除数组的最后一个元素
arr.pop()
print(arr) # 输出:[0, 10, 20, 2, 3, 4]
# 删除数组中值为20的元素
arr.remove(20)
print(arr) # 输出:[0, 10, 2, 3, 4]
除了列表之外,Python 还提供了 array 模块,可以用来创建固定类型的数组。例如,以下代码创建一个包含10个整数的数组:
import array
arr = array.array('i', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
其中 ‘i’ 表示数组中的元素类型为整数。除了 ‘i’,array 模块还支持其他的类型码,例如 ‘f’ 表示单精度浮点数,‘d’ 表示双精度浮点数等等。array 模块中还提供了一些方法。在 Python 中,可以使用内置的 list 类型来实现数组。Python 中的 list 类型实际上是一种动态数组,可以存储任意类型的元素,并且支持动态调整大小。
以下是一些常用的 list 操作方法:
创建一个空的列表:my_list = []
创建一个包含指定元素的列表:my_list = [1, 2, 3]
获取列表长度:len(my_list)
访问列表中的元素:my_list[index]
修改列表中的元素:my_list[index] = new_value
向列表尾部添加一个元素:my_list.append(value)
在指定位置插入一个元素:my_list.insert(index, value)
从列表中删除一个元素:my_list.remove(value)
从列表中删除指定位置的元素:my_list.pop(index)
查找指定元素在列表中的位置:my_list.index(value)
判断一个元素是否在列表中:value in my_list
需要注意的是,Python 中的 list 类型实现方式是基于动态数组的,因此在对列表进行频繁的插入或删除操作时,性能可能会受到影响。如果需要高效地进行频繁的插入或删除操作,可以考虑使用链表或其他数据结构。
**
二、链表
**
链表是一种常见的数据结构,它是由若干个节点组成的序列,每个节点包含数据和指向下一个节点的指针。链表可以分为单向链表、双向链表和循环链表等不同类型。Python中可以使用类来实现链表,具体实现方法如下:
首先,定义链表节点类,包含节点的数据和指向下一个节点的指针:
class Node:
def __init__(self, data):
self.data = data
self.next = None
然后,定义链表类,包含链表头和链表尾指针:
class LinkedList:
def __init__(self):
self.head = None
self.tail = None
接着,实现链表的基本操作,例如在链表头部添加节点、在链表尾部添加节点、在指定位置添加节点、删除节点、查找节点等:
class LinkedList:
...
def add_first(self, data):
new_node = Node(data)
if not self.head:
self.head = self.tail = new_node
else:
new_node.next = self.head
self.head = new_node
def add_last(self, data):
new_node = Node(data)
if not self.head:
self.head = self.tail = new_node
else:
self.tail.next = new_node
self.tail = new_node
def add_at(self, index, data):
new_node = Node(data)
if not self.head:
self.head = self.tail = new_node
elif index == 0:
new_node.next = self.head
self.head = new_node
else:
node = self.head
for i in range(index - 1):
if node.next is None:
break
node = node.next
new_node.next = node.next
node.next = new_node
def remove(self, data):
if not self.head:
return
elif self.head.data == data:
self.head = self.head.next
else:
node = self.head
while node.next:
if node.next.data == data:
node.next = node.next.next
if node.next is None:
self.tail = node
break
node = node.next
def find(self, data):
node = self.head
while node:
if node.data == data:
return node
node = node.next
return None
最后,可以使用链表类来创建一个具有一定功能的链表实例:
ll = LinkedList()
ll.add_first(1)
ll.add_first(2)
ll.add_last(3)
ll.add_at(1, 4)
ll.remove(2)
node = ll.find(3)
if node:
print(node.data)
这样,就可以用Python实现链表数据结构了。
二.1单链表实现:
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def add_node(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
else:
current = self.head
while current.next is not None:
current = current.next
current.next = new_node
def delete_node(self, data):
if self.head is None:
return
if self.head.data == data:
self.head = self.head.next
return
current = self.head
while current.next is not None:
if current.next.data == data:
current.next = current.next.next
return
current = current.next
def print_list(self):
current = self.head
while current is not None:
print(current.data)
current = current.next
二、2双向链表实现
class Node:
def __init__(self, data):
self.data = data
self.prev = None
self.next = None
class DoublyLinkedList:
def __init__(self):
self.head = None
def add_node(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
else:
current = self.head
while current.next is not None:
current = current.next
current.next = new_node
new_node.prev = current
def delete_node(self, data):
if self.head is None:
return
if self.head.data == data:
self.head = self.head.next
self.head.prev = None
return
current = self.head
while current.next is not None:
if current.next.data == data:
current.next = current.next.next
if current.next is not None:
current.next.prev = current
return
current = current.next
def print_list(self):
current = self.head
while current is not None:
print(current.data)
current = current.next
二、3双向循环链表
class Node:
def __init__(self, data=None, prev=None, next=None):
self.data = data
self.prev = prev
self.next = next
class DoublyCircularLinkedList:
def __init__(self):
self.head = None
def is_empty(self):
return self.head == None
def add(self, data):
new_node = Node(data)
if self.is_empty():
self.head = new_node
new_node.prev = new_node
new_node.next = new_node
else:
new_node.prev = self.head.prev
new_node.next = self.head
self.head.prev.next = new_node
self.head.prev = new_node
def insert(self, index, data):
new_node = Node(data)
if self.is_empty():
self.head = new_node
new_node.prev = new_node
new_node.next = new_node
else:
cur_node = self.head
for i in range(index-1):
cur_node = cur_node.next
new_node.prev = cur_node
new_node.next = cur_node.next
cur_node.next.prev = new_node
cur_node.next = new_node
if index == 0:
self.head = new_node
def remove(self, data):
if self.is_empty():
return
cur_node = self.head
while cur_node.data != data:
cur_node = cur_node.next
if cur_node == self.head:
return
if cur_node == self.head:
self.head = cur_node.next
cur_node.prev.next = cur_node.next
cur_node.next.prev = cur_node.prev
def print_list(self):
if self.is_empty():
print("List is empty")
return
cur_node = self.head
while True:
print(cur_node.data, end=" ")
cur_node = cur_node.next
if cur_node == self.head:
break
print()
# Test
dll = DoublyCircularLinkedList()
dll.add(1)
dll.add(2)
dll.add(3)
dll.insert(0, 0)
dll.insert(4, 4)
dll.remove(2)
dll.print_list()
上述代码中,Node 类表示链表的节点,包含数据、前驱节点和后继节点;DoublyCircularLinkedList 类表示双向循环链表,包含一个指向链表头节点的 head 属性,is_empty、add、insert、remove、print_list
等操作方法。在 add 方法中,如果链表为空,则将新节点作为头节点,并使其前驱和后继都指向自身;否则将新节点插入到链表尾部,同时将新节点的前驱指向链表尾节点,后继指向头节点,头节点的前驱指向新节点;在 insert 方法中,如果链表为空,则将新节点作为头节点,并使其前驱和后继都指向自身;否则将新节点插入到指定位置,同时修改前驱和后继节点的指针。在 remove 方法中,遍历链表,找到待删除节点并修改前驱和后继节点的指针即可。
二、4静态链表
静态链表(Static Linked List)是指使用数组来模拟链表的一种数据结构。它的实现思想是将链表中的结点通过一个数组来存储,同时利用数组元素的下标来表示链表中结点的指针。
在静态链表中,数组中的每个元素(或称为“节点”)由两个部分组成,一个是存储数据的域,另一个是指向下一个元素(节点)的指针域。由于静态链表的结构可以预先分配,因此在一些空间有限、需要高效利用空间的场合下,使用静态链表是一种比较实用的方法。
下面是一个简单的 Python 实现,实现了静态链表的初始化、添加元素、删除元素等基本操作。
class Node:
def __init__(self, value, next):
self.value = value
self.next = next
class StaticLinkedList:
def __init__(self, capacity):
self.head = None
self.capacity = capacity
self.nodes = [Node(None, i+1) for i in range(capacity)]
self.nodes[capacity-1].next = 0
def is_full(self):
return self.nodes[0].next == 0
def is_empty(self):
return self.head is None
def get_next(self, index):
return self.nodes[index].next
def insert(self, value):
if self.is_full():
raise Exception("Static linked list is full")
new_node_index = self.nodes[0].next
new_node = self.nodes[new_node_index]
new_node.value = value
self.nodes[0].next = new_node.next
if self.is_empty():
new_node.next = 0
else:
new_node.next = self.head.next
self.head = new_node
def delete(self, value):
if self.is_empty():
raise Exception("Static linked list is empty")
prev_node = None
current_node = self.nodes[self.head.next]
while current_node.value != value:
prev_node = current_node
current_node = self.nodes[current_node.next]
if current_node == self.head:
raise Exception("Node with value {} not found".format(value))
if prev_node is None:
self.head = None
else:
prev_node.next = current_node.next
self.nodes[current_node.next].next = current_node.next
current_node.next = self.nodes[0].next
self.nodes[0].next = self.nodes.index(current_node)
current_node.value = None
在这个实现中,Node 类表示静态链表中的一个节点,包含两个成员变量 value 和 next,分别表示节点存储的值和指向下一个节点的指针。StaticLinkedList 类表示静态链表,包含了一些基本的操作,如 insert 和 delete 等,还有一些辅助方法,如 is_full 和 is_empty 等,用于判断静态链表是否已满或为空。
链表是一种基本的数据结构,可以用来表示线性结构,如数组、字符串等。相较于数组,链表的插入和删除操作更加灵活和高效,但访问特定位置的元素需要遍历整个链表,效率较低。
链表有多种类型,如单向链表、双向链表、循环链表、静态链表等,它们各自具有特定的优缺点和应用场景。
在 Python 中实现链表可以使用类来表示节点,节点包含数据和指向下一个节点(和前一个节点,如果是双向链表)的指针。对于单向链表和双向链表,我们可以通过指针操作来实现插入、删除和访问等操作。循环链表和双向循环链表在实现上也类似,只需在链表尾部节点的指针指向头部节点即可。
静态链表是一种在数组基础上实现的链表,它通过将数组元素当作节点,使用数组下标作为指针来实现链表的指向,同时还需要一个空闲链表来存储未被占用的节点。静态链表在实现上相对复杂,但可以节省空间和避免动态分配内存的问题。在使用链表时,需要注意链表为空或链表长度不足的情况,以及避免出现循环引用等问题。
以上便是本节内容,有不足请指出,笔者会耐心细致的去看完。下节更新数据结构线性表的栈和队列,有需要的小伙伴可以关注我之后的更新。谢谢各位。