链表是由一个个被系统随机分配地址的结点们通过指针进行相连,以c++为例子,在写链表的时候可以使用结构体进行实现:
struct node
{
ElemType value;
ndoe * next;
};
*next指向下一个结点的地址,那么在Python中是怎么指向下一个结构体的地址呢?
这就不得不提到等号。在Python中,如果要交换两个变量的值,那么可以这样写:
a = 10
b = 20
a,b = b,a
问题来了:为什么在Python中可以写成a,b=b,a
,而其它语言进行变量值的交换则为(以c++为例子)tmp=b,b=a,a=tmp
?如果使用id查看交换前后a、b的地址话,那么会发现一个现象:地址是不变的!
这就不得不说Python的机制了:在Python中,一切皆为对象。
链表是线性表,满足(除头尾结点外)有唯一的一个前驱和唯一的一个后继
单链表是链表最简单的形式,每个结点有两个域,一个是值域,另一个是指针域,指针域指向下一个结点的地址,最后一个结点的指针域为空。单链表的实现有两种方法,一种是带头结点,一种是不带头结点,图中所示为不带头结点的单链表。
单链表中结点的定义
class SingleNode(object):
def __init__(self,item):
self.item = item
self.next = None
class Node(object):
"""结点"""
def __init__(self, elem):
self.elem = elem
self.next = None
class SingleLinkList(object):
"""单链表"""
def __init__(self, Node = None):
self.__head = Node
def is_empty(self):
return self.__head == None
def length(self):
cur = self.__head
cnt = 0
while cur != None:
cnt += 1
cur = cur.next
return cnt
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):
"""插入尾节点"""
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, pose, item):
"""在指定位置插入结点"""
if pose<=0:
self.add(item)
elif pose >= self.length()-1:
self.append(item)
else:
node = Node(item)
cnt = 1
cur = self.__head
pre = None
while cnt != pose:
pre = cur
cur = cur.next
cnt += 1
cur = node
cur.next = pre.next
pre.next = cur
def remove(self, item):
if self.is_empty():
print("链表为空,删除操作错误!")
else:
cur = self.__head
pre = None
while cur.elem != item:
pre = cur
cur = cur.next
pre.next = cur.next0
print("删除成功!")
del cur
def search(self, item):
cur = self.__head
while cur.elem != item:
cur = cur.next
print("查找成功")
pass
if __name__ == "__main__":
l = SingleLinkList()
print(l.is_empty())
print(l.length())
l.append(1)
print(l.is_empty())
print(l.length())
l.add(0)
l.append(2)
l.append(3)
l.append(4)
l.append(5)
l.append(6)
l.insert(255, 100)
l.travel()
其中,从函数的实现中可以看出来各个函数的时间复杂度:
双链表就是在结点中增加一个指针域,该指针域指向该结点的前驱结点。头结点没有前驱结点、尾节点没有后驱结点。
双链表的操作:
注意该操作,操作4进行之前必须要进行操作3,否则会丢失数据。
删除元素:
双链表的实现:
class Node(object):
"""双向链表节点"""
def __init__(self, item):
self.item = item
self.next = None
self.prev = None
class DLinkList(object):
"""双向链表"""
def __init__(self):
self._head = 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.item,
cur = cur.next
print ""
def add(self, item):
"""头部插入元素"""
node = Node(item)
if self.is_empty():
# 如果是空链表,将_head指向node
self._head = node
else:
# 将node的next指向_head的头节点
node.next = self._head
# 将_head的头节点的prev指向node
self._head.prev = node
# 将_head 指向node
self._head = node
def append(self, item):
"""尾部插入元素"""
node = Node(item)
if self.is_empty():
# 如果是空链表,将_head指向node
self._head = node
else:
# 移动到链表尾部
cur = self._head
while cur.next != None:
cur = cur.next
# 将尾节点cur的next指向node
cur.next = node
# 将node的prev指向cur
node.prev = cur
def search(self, item):
"""查找元素是否存在"""
cur = self._head
while cur != None:
if cur.item == item:
return True
cur = cur.next
return False
当单向链表的尾节点不指向None,而是指向头结点的时候,那么就构成了一个单向循环链表。
单循环链表中一些操作的时间复杂度
单循环链表代码实现:
class Node(object):
"""节点"""
def __init__(self, item):
self.item = item
self.next = None
class SinCycLinkedlist(object):
"""单向循环链表"""
def __init__(self):
self._head = None
def is_empty(self):
"""判断链表是否为空"""
return self._head == None
def length(self):
"""返回链表的长度"""
# 如果链表为空,返回长度0
if self.is_empty():
return 0
count = 1
cur = self._head
while cur.next != self._head:
count += 1
cur = cur.next
return count
def travel(self):
"""遍历链表"""
if self.is_empty():
return
cur = self._head
print cur.item,
while cur.next != self._head:
cur = cur.next
print cur.item,
print ""
def add(self, item):
"""头部添加节点"""
node = Node(item)
if self.is_empty():
self._head = node
node.next = self._head
else:
#添加的节点指向_head
node.next = self._head
# 移到链表尾部,将尾部节点的next指向node
cur = self._head
while cur.next != self._head:
cur = cur.next
cur.next = node
#_head指向添加node的
self._head = node
def append(self, item):
"""尾部添加节点"""
node = Node(item)
if self.is_empty():
self._head = node
node.next = self._head
else:
# 移到链表尾部
cur = self._head
while cur.next != self._head:
cur = cur.next
# 将尾节点指向node
cur.next = node
# 将node指向头节点_head
node.next = self._head
def insert(self, pos, item):
"""在指定位置添加节点"""
if pos <= 0:
self.add(item)
elif pos > (self.length()-1):
self.append(item)
else:
node = Node(item)
cur = self._head
count = 0
# 移动到指定位置的前一个位置
while count < (pos-1):
count += 1
cur = cur.next
node.next = cur.next
cur.next = node
def remove(self, item):
"""删除一个节点"""
# 若链表为空,则直接返回
if self.is_empty():
return
# 将cur指向头节点
cur = self._head
pre = None
# 若头节点的元素就是要查找的元素item
if cur.item == item:
# 如果链表不止一个节点
if cur.next != self._head:
# 先找到尾节点,将尾节点的next指向第二个节点
while cur.next != self._head:
cur = cur.next
# cur指向了尾节点
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.item == item:
# 删除
pre.next = cur.next
return
else:
pre = cur
cur = cur.next
# cur 指向尾节点
if cur.item == item:
# 尾部删除
pre.next = cur.next
def search(self, item):
"""查找节点是否存在"""
if self.is_empty():
return False
cur = self._head
if cur.item == item:
return True
while cur.next != self._head:
cur = cur.next
if cur.item == item:
return True
return False
if __name__ == "__main__":
ll = SinCycLinkedlist()
ll.add(1)
ll.add(2)
ll.append(3)
ll.insert(2, 4)
ll.insert(4, 5)
ll.insert(0, 6)
print "length:",ll.length()
ll.travel()
print ll.search(3)
print ll.search(7)
ll.remove(1)
print "length:",ll.length()
ll.travel()