单链表引入
-
顺序表
-
理解Python变量的本质: 变量存储的不是值,是值的地址
-
理解Python的 "="表示的是指向关系
-
案例: 交换a,b的值, a=10, b=20
-
a, b = 20, 10
-
t0: a这块内存(也有id), 存储的是10这个值的地址(可能是0x111), b存储的是20这个值(整型4个字节)的地址(可能是0x222)
-
t1: a现在指向b的值的地址(a存储0x222), b指向(存储)10的地址(0x111)
-
Pyhton变量的本质: 指针. 所以Pyhton在定义变量时不必声明变量类型, 因为Pyhton变量根本就不直接存储值, 存储的是值的地址, 通过地址去取值.
-
真正理解: Pyhton 一切皆对象(存地址嘛, 变量, 容器, 函数, 类...都只是一块地址而已), so 常看到把一个类, 一个函数=给一个变量,就不足为奇了.
a, b = 10, 20
print('交换前',a,b)
a, b = b, a
print('交换后',a, b)
交换前 10 20
交换后 20 10
def add(x, y):
return x + y
print(add(3,4))
7
f = add
print(f(3,4))
7
构造节点类
-
为什么要用类: 节点 = 数据取 + 指针区(指向下一个节点的地址)
-
类: 属性 + 操作的封装
插入: Python3定义类用不用继承object的区别
class A:
name = "youge"
class B(object):
name = 'youge'
if __name__ == '__main__':
a, b = A(), B()
print('无object的类拥有:', dir(a))
print('有object的类拥有:', dir(b))
无object的类拥有: ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']
有object的类拥有: ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']
class Node(object):
""""节点类""""
def __init__(self, data=None):
self.data = data
self.next = None # Pyhton 的 "=" 就直接想象成 ----> 指向即可(指向下一个节点对象)
node1 = Node(123)
print('这是一个节点对象, 包含属性和操作', node1)
print(f'该节点的数据是:{node1.data}, 指向的节点对象是:{node1.next}')
这是一个节点对象, 包含属性和操作 <__main__.Node object at 0x0000021B939406A0>
该节点的数据是:123, 指向的节点对象是:None
单链表类ADT
-
is_empty() 判断链表是否为空
-
lenghth() 链表的长度(元素个数)
-
travel 遍历整个链表
-
add(item) 从链表头部增加元素(值)
-
append(item) 从链表尾部增加元素
-
insert(pos, item) 从指定位置(下标)增加元素
-
remove(item) 删除节点
-
search(item)
-
都是对象方法, 非类方法, 实现时先结构化写出来pass慢慢去实现
class Node(object):
"""节点类""""
def __init__(self, data=None):
self.data = data
self.next = None
class SingleLinkList(object):
"""单链表"""
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(item):
pass
# 调用
s_lst = SingleLinkList()
s_lst.is_empty()
s_lst.length()
s_lst.travel()
s_lst.add(123)
....
头节点: 将一个节点挂在到单链表中来
class Node(object):
"""节点类"""
def __init__(self, data=None):
self.data = data
self.next = None
class SingleLinkList(object):
"""单链表"""
def __init__(self, node=None):
self.head = node
self.next = None
node1 = Node(111)
sl_obj = SingleLinkList(node1)
print('将节点对象传给链表的head属性:', sl_obj.head)
print('属性是一个对象, 访问值用对象.属性来访问:', sl_obj.head.data)
将节点对象传给链表的head属性: <__main__.Node object at 0x0000021B93710828>
属性是一个对象, 访问值用对象.属性来访问: 111
为什么需要两个类
-
理解Node类和SingleListLink类 的运作过程
link = SigleLinkList()
node = Node(111)
is_empyt 实现
class Node(object):
"""节点类"""
def __init__(self, data=None):
self.data = data
self.next = None
class SingleLinkList(object):
"""单链表"""
def __init__(self, node=None):
self.__head = node
self.next = None
def is_empty(self):
"""链表是否为空"""
return self.__head == None
def length(self):
"""链表的长度"""
pass
length实现
class Node(object):
"""节点类"""
def __init__(self, data=None):
self.data = data
self.next = None
class SingleLinkList(object):
"""单链表"""
def __init__(self, node=None):
self.__head = node
self.next = None
def is_empty(self):
"""链表是否为空"""
return self.__head == None
def length(self):
"""链表的长度"""
cur = self.__head
count = 0
while cur != None:
count += 1
cur = cur.next
return count
travel 实现
class Node(object):
"""节点类"""
def __init__(self, data=None):
self.data = data
self.next = None
class SingleLinkList(object):
"""单链表"""
def __init__(self, node=None):
self.__head = node
self.next = None
def is_empty(self):
"""链表是否为空"""
return self.__head == None
def length(self):
"""链表的长度"""
cur = self.__head
count = 0
while cur != None:
count += 1
cur = cur.next
return count
def travel(self):
"""元素遍历"""
cur = self.__head
while cur != None:
print(cur.data)
cur = cur.next
append 实现(尾插法)
-
尾部插入元素: 即遍历到最后一节点, 将其next指向插入的元素节点即可
-
首先要将用户给定的元素(值), 作为一个节点对象(data,next)
-
__ head -> 111 ->222 ->None -> (333, None)
class Node(object):
"""节点类"""
def __init__(self, data=None):
self.data = data
self.next = None
class SingleLinkList(object):
"""单链表"""
def __init__(self, node=None):
self.__head = node
self.next = None
def is_empty(self):
"""链表是否为空"""
return self.__head == None
def length(self):
"""链表的长度"""
cur = self.__head
count = 0
while cur != None:
count += 1
cur = cur.next
return count
def travel(self):
"""元素遍历"""
cur = self.__head
while cur != None:
print(cur.data, end=' ' )
cur = cur.next
def append(self, item):
"""尾部添加元素"""
node = Node(item)
cur = self.__head
if self.is_empty():
self.__head = node
else:
while cur.next != None:
cur = cur.next
cur.next = node
is_empty, length, travel 测试
l = SingleLinkList()
print(l.is_empty())
print(l.length())
l.append(0)
print(l.is_empty())
print(l.length())
for i in range(8):
l.append(i)
l.travel()
True
0
False
1
0 0 1 2 3 4 5 6 7
add 实现(头插法)
-
构建要插入的节点对象
-
头插的顺序是先让新元素的next->其余节点, 然后链表的__ head -> node
class Node(object):
"""节点类"""
def __init__(self, data=None):
self.data = data
self.next = None
class SingleLinkList(object):
"""单链表"""
def __init__(self, node=None):
self.__head = node
self.next = None
def is_empty(self):
"""链表是否为空"""
return self.__head == None
def length(self):
"""链表的长度"""
cur = self.__head
count = 0
while cur != None:
count += 1
cur = cur.next
return count
def travel(self):
"""元素遍历"""
cur = self.__head
while cur != None:
print(cur.data, end=' ' )
cur = cur.next
def append(self, item):
"""尾部添加元素"""
node = Node(item)
cur = self.__head
if self.is_empty():
self.__head = node
else:
while cur.next != None:
cur = cur.next
cur.next = node
def add(self, item):
"""从头部插入元素"""
node = Node(item)
node.next = self.__head.next
self.__head = node
l = SingleLinkList()
print(l.is_empty())
print(l.length())
l.append(0)
print(l.is_empty())
print(l.length())
for i in range(8):
l.append(i)
l.add(666)
l.travel()
True
0
False
1
666 0 1 2 3 4 5 6 7
insert 实现
-
从任意位置插入元素: 如何定位pos(下标)
-
找到要插入的位置下标: count计数
-
用该位置的该node的next->当前位置节点, 前一个节点的Next指向该node, 注意顺序哦
class Node(object):
"""节点类"""
def __init__(self, data=None):
self.data = data
self.next = None
class SingleLinkList(object):
"""单链表"""
def __init__(self, node=None):
self.__head = node
self.next = None
def is_empty(self):
"""链表是否为空"""
return self.__head == None
def length(self):
"""链表的长度"""
cur = self.__head
count = 0
while cur != None:
count += 1
cur = cur.next
return count
def travel(self):
"""元素遍历"""
cur = self.__head
while cur != None:
print(cur.data, end=' ' )
cur = cur.next
def append(self, item):
"""尾部添加元素"""
node = Node(item)
cur = self.__head
if self.is_empty():
self.__head = node
else:
while cur.next != None:
cur = cur.next
cur.next = node
def add(self, item):
"""从头部插入元素"""
node = Node(item)
node.next = self.__head.next
self.__head = node
def insert(self, pos, item):
"""从任意位置插入元素"""
if pos <= 0:
self.add(item)
elif pos > (self.length()-1):
self.append(item)
else:
node = Node(item)
pre = self.__head
count = 0
while count < (pos-1):
count += 1
pre = pre.next
node.next = pre.next
pre.next = node
l = SingleLinkList()
print(l.is_empty())
print(l.length())
l.append(0)
print(l.is_empty())
print(l.length())
for i in range(8):
l.append(i)
l.add(666)
l.insert(-1, 999)
l.insert(2, 6699)
l.insert(888,999)
l.insert(5,'cj')
l.travel()
True
0
False
1
999 0 6699 1 2 cj 3 4 5 6 7 999
search实现
class Node(object):
"""节点类"""
def __init__(self, data=None):
self.data = data
self.next = None
class SingleLinkList(object):