链表:
链表和数组都是线性表:
数组:将元素顺序地存放在一块连续的存储区内,元素间的顺序关系由它们的存储顺序自然表示。
链表:将元素存放在通过链接构造起来的一系列存储块中。
特点:不用连续存储,不需要知道存储的数量,分散存储。
寻找元素的方式:比如有个list li = [200,400,600]
200这个元素存储着400的内存地址,400存储着600的内存地址,
既一个链表元素存储着两个东西:1、数据区2、链接区
单向链表:
前一个节点指向下一个节点,单向的。尾节点的链接区指向为空。
通过类实现以下功能
单链表的操作
- is_empty() 链表是否为空
- length() 链表长度
- travel() 遍历整个链表
- add(item) 链表头部添加元素
- append(item) 链表尾部添加元素
- insert(pos, item) 指定位置添加元素
- remove(item) 删除节点
- search(item) 查找节点是否存在
在例如c语言中,申明一个变量需要规定好这个变量的类型,例如:int a = 10,这是因为c在申明变量后,会在内存中
划出一个空间存放10,这个空间的别名为a,a就算改变也只能是int类型,而在python中 a = 10的意思是a
代表着内存,存放着数字10的内存地址,既指针概念,换成其他类型也不影响(例如浮点,函数等)。
一个元素有两个属性:
1、elem 为此元素的值
2、next为指向下一个元素位置的内存地址
class Node:#元素
def __init__(self,elem):
self.elem = elem#此节点的数值
self.next = None#下一个节点的内存地址
class SingleLinkList:#单向链表
def __init__(self):
self._head = None
def is_empty(self):#链表是否为空
pass
def length(self):#链表长度
pass
def travel(self):# 遍历整个链表
pass
def add(self,item):#链表头部添加元素
pass
def append(self,item):#链表尾部添加元素
pass
def insert(self,pos, item):#指定位置添加元素
pass
def remove(self,item):#删除节点
pass
def search(self,item):#查找节点是否存在
pass
先定义两个类,节点和单向链表。
初始化链表,链表的头元素(_head=None)为None空,要想向链表添加一个节点,则必须先实例化一个Node对象。
sll = SingleLinkList()
node = Node(100)
向sll链表添加一个节点100,则sll._head 指向100。
is_empty
现在可以写出is_empty的方法,当_head == None则表示链表为空。
def is_empty(self): # 链表是否为空
return self._head == None
length
要想实现知道链表里元素的个数,则需要一个指针或者游标来计数。
计数初始,游标在_head处,然后通过_head指向的头节点找到第一个节点,然后再从第一个节点的链接self.next找到下一个节点。
判断是否是最后一个节点的标志是此时节点的next属性是否为None,如果为None则是最后一个节点。
def length(self): # 链表长度
#要考虑到链表为空的情况
count = 0
cur = self._head#游标
while cur != None:
count += 1
cur = cur.next
return count
同理,遍历也可以写出来
travel
def travel(self): # 遍历整个链表
cur = self._head#游标
while cur != None:
print(cur.elem)
cur = cur.next
append
def append(self, item): # 链表尾部添加元素 item为数据,不是节点,让用户使用起来方便,只要用户输入数字
node = Node(item)
if self.is_empty():
self._head = node
else:
cur = self._head
while cur.next != None:
cur = cur.next
cur.next = node
insert
def insert(self, pos, item): # 指定位置添加元素
count = 0
cur = self.__head
if pos <= 0:
self.add(item)
elif pos > self.length() - 1:
self.append(item)
else:
while count < pos - 1:#在指定位置的前一个节点,插入新的节点,
cur = cur.next#游标指向下一个
count += 1
node = Node(item)
node.next = cur.next#新的节点的下一个节点指向原来位置为pos的节点
cur.next = node#然后在把游标的下一个节点指向要插入的节点,要注意先后顺序
remove
def remove(self, item): # 删除节点
cur = self.__head#游标在第一个节点
prev = None#此时游标的上一个位置为None
while cur != None:#当游标部位不为空时
if cur.elem == item:#找到要删除逇数字
if cur == self.__head:#如果要删除的节点为第一个节点
self.__head == cur.next#把首节点指向第二个节点
else:
prev.next = cur.next#其余情况下则把要删除节点的上一个节点指向下一个节点
break
else:
prev = cur
cur = cur.next
search
def search(self, item): # 查找节点是否存在
cur = self.__head#游标
while cur != None:
if cur.elem == item:
return True
else:
cur = cur.next
return False
完整版:
class Node: # 元素
def __init__(self, elem):
self.elem = elem # 此节点的数值
self.next = None # 下一个节点的内存地址
class SingleLinkList: # 单向链表
def __init__(self):
self.__head = None
def is_empty(self): # 链表是否为空
return self.__head == None
def length(self): # 链表长度
#要考虑到链表为空的情况
count = 0
cur = self.__head#游标
while cur != None:
count += 1
cur = cur.next
return count
def travel(self): # 遍历整个链表
cur = self.__head#游标
while cur != None:
print(cur.elem, end=" ")
cur = cur.next
def add(self, item): # 链表头部添加元素
node = Node(item)
node.next = self.__head
self.__head = node
def append(self, item): # 链表尾部添加元素 item为数据,不是节点,让用户使用起来方便,只要用户输入数字
node = Node(item)
if self.is_empty():
self.__head = node
else:
cur = self.__head
while cur.next != None:
cur = cur.next
cur.next = node
def insert(self, pos, item): # 指定位置添加元素
count = 0
cur = self.__head
if pos <= 0:
self.add(item)
elif pos > self.length() - 1:
self.append(item)
else:
while count < pos - 1:#在指定位置的前一个节点,插入新的节点,
cur = cur.next#游标指向下一个
count += 1
node = Node(item)
node.next = cur.next#新的节点的下一个节点指向原来位置为pos的节点
cur.next = node#然后在把游标的下一个节点指向要插入的节点,要注意先后顺序
def remove(self, item): # 删除节点
cur = self.__head#游标在第一个节点
prev = None#此时游标的上一个位置为None
while cur != None:#当游标部位不为空时
if cur.elem == item:#找到要删除逇数字
if cur == self.__head:#如果要删除的节点为第一个节点
self.__head == cur.next#把首节点指向第二个节点
else:
prev.next = cur.next#其余情况下则把要删除节点的上一个节点指向下一个节点
break
else:
prev = cur
cur = cur.next
def search(self, item): # 查找节点是否存在
cur = self.__head#游标
while cur != None:
if cur.elem == item:
return True
else:
cur = cur.next
return False
if __name__ == '__main__':
sll = SingleLinkList()
print("是否为空",sll.is_empty())
print("链表长度",sll.length())
sll.append(1)
sll.append(2)
sll.append(3)
sll.append(4)
sll.travel()
sll.remove(4)
sll.travel()
sll.remove(3)
sll.travel()