python中的列表是采用链式结构实现的_数据结构复习——用python实现链表

本文介绍了如何使用Python实现单向链表数据结构,包括节点类和链表类的定义,详细展示了添加、删除、查找、更新节点等操作的实现代码,并提到了双向链表和循环链表的概念。
摘要由CSDN通过智能技术生成

最近开始复习数据结构和算法,发现以前学过的知识遗忘了许多,得重新看看,写写代码。

单向链表

链表(link list)是一种非常基本的数据结构,与数组相比,链表的特点是内存是不连续的,前一个元素存储地址的下一个地址中存储的不一定是下一个元素。链表通过一个指向下一个元素地址的引用将链表中的元素串起来。

链表的基本单位是节点,节点包括一个值和一个指针:

节点类的实现十分简单:

class Node:

"""

节点类

"""

def __init__(self, value, next=None):

self.value = value

self.next = next

def get_data(self):

return self.value

def set_new_data(self, new_value):

self.value = new_value

有了节点类之后就可以实现链表类了,链表的一般操作有add(),insert(),find(),delete()等,时间复杂度均为O(n),都需要从头遍历链表。

链表类:

class LinkList(object):

"""

单向链表类

"""

def __init__(self, head=None):

self.head = head #初始化头点,是一个Node类

if not self.head:

self.length = 1

else:

self.length = 0

def get_head(self):

return self.head

def is_empty(self):

if not self.length:

return True

添加节点:

def append_node(self, data_or_node):

item = None

if isinstance(data_or_node, Node):

item = data_or_node

else:

item = Node(data_or_node)

if not self.head:

self.head = item

self.length += 1

else:

node = self.head #头节点始终保持不变

while node.next:

node = node.next

node.next = item

self.length += 1

#若头节点是指最近添加的节点

# self.head.next = item

# self.head = item

删除节点:

def delete_node(self, index):

if self.is_empty():

print("this link list is empty.")

return

if index<0 or index>=self.length:

print("error:out of index.")

return

if index == 0:

self.head = self.head.next

self.length -= 1

return

node = self.head

pre = self.head

while node.next and index:

pre = node

node = node.next

index -= 1

if not index:

pre.next = node.next

self.length -= 1

更新节点:

def update_node(self, index, value):

if self.is_empty() or index<0 or index>=self.length:

print("error:out of index.")

return

node = self.head

while node.next and index:

node = node.next

index -= 1

if not index:

node.value = value

查找节点:

def get_node(self, index):

if self.is_empty() or index<0 or index>=self.length:

print("error:out of index.")

return

node = self.head

while node.next and index:

node = node.next

index -= 1

if not index:

return node.value

def get_index(self, value):

if self.is_empty():

print("this link list is empty.")

return

node = self.head

j = 0

while node:

if node.value == value:

return j

else:

node = node.next

j += 1

if j == self.length:

print("%s not found" % str(value))

return

插入节点:(不好截图,就直接复制代码了)

插入节点的时候要注意从插入在头节点前的情况。

def insert_node(self, index, data_or_node):

if self.is_empty():

print("this link list is empty.")

return

if self.is_empty() or index<0 or index>=self.length:

print("error:out of index.")

return

item = None

if isinstance(data_or_node, Node):

item = data_or_node

else:

item = Node(data_or_node)

if index == 0:

item.next = self.head

self.head = item

self.length += 1

return

node = self.head

pre = self.head

while node.next and index:

pre = node

node = node.next

index -= 1

if not index:

pre.next = item

item.next = node

self.length += 1

清空链表:

def clear(self):

self.head = None

self.length = 0

源码如下:

class Node:

"""

节点类

"""

def __init__(self, value, next=None):

self.value = value

self.next = next

def get_data(self):

return self.value

def set_new_data(self, new_value):

self.value = new_value

class LinkList(object):

"""

单向链表类

"""

def __init__(self, head=None):

self.head = head #初始化头点,是一个Node类

if not self.head:

self.length = 1

else:

self.length = 0

def get_head(self):

return self.head

def is_empty(self):

if not self.length:

return True

def append_node(self, data_or_node):

item = None

if isinstance(data_or_node, Node):

item = data_or_node

else:

item = Node(data_or_node)

if not self.head:

self.head = item

self.length += 1

else:

node = self.head #头节点始终保持不变

while node.next:

node = node.next

node.next = item

self.length += 1

#若头节点是指最近添加的节点

# self.head.next = item

# self.head = item

def delete_node(self, index):

if self.is_empty():

print("this link list is empty.")

return

if index<0 or index>=self.length:

print("error:out of index.")

return

if index == 0:

self.head = self.head.next

self.length -= 1

return

node = self.head

pre = self.head

while node.next and index:

pre = node

node = node.next

index -= 1

if not index:

pre.next = node.next

self.length -= 1

def update_node(self, index, value):

if self.is_empty() or index<0 or index>=self.length:

print("error:out of index.")

return

node = self.head

while node.next and index:

node = node.next

index -= 1

if not index:

node.value = value

def get_node(self, index):

if self.is_empty() or index<0 or index>=self.length:

print("error:out of index.")

return

node = self.head

while node.next and index:

node = node.next

index -= 1

if not index:

return node.value

def get_index(self, value):

if self.is_empty():

print("this link list is empty.")

return

node = self.head

j = 0

while node:

if node.value == value:

return j

else:

node = node.next

j += 1

if j == self.length:

print("%s not found" % str(value))

return

def insert_node(self, index, data_or_node):

if self.is_empty():

print("this link list is empty.")

return

if self.is_empty() or index<0 or index>=self.length:

print("error:out of index.")

return

item = None

if isinstance(data_or_node, Node):

item = data_or_node

else:

item = Node(data_or_node)

if index == 0:

item.next = self.head

self.head = item

self.length += 1

return

node = self.head

pre = self.head

while node.next and index:

pre = node

node = node.next

index -= 1

if not index:

pre.next = item

item.next = node

self.length += 1

def clear(self):

self.head = None

self.length = 0

以上实现的是单向链表,除了单向链表之外还存在双向链表,循环链表等。

双向链表

双向链表就是有两个方向的链表。同单向链表不同,在双向链表中每一个节点不仅存储指向下一个节点的指针,而且存储指向前一个节点的指针。通过这种方式,能够通过在O(1)时间内通过目的节点直接找到前驱节点,但是同时会增加大量的指针存储空间。

双向链表与单向链表的实现大同小异,只不过是增加了前向指针。

class Node(object):

def __init__(self, value, p=None):

self.data = value

self.next = p

self.prev = p

# 如果加入尾节点tail,代码会更简单

class LinkList(object):

def __init__(self, head=None):

self.head = head

if not head:

self.length = 1

else:

self.length = 0

def is_empty(self):

if not self.length:

return True

def append(self, data_or_node):

item = None

if isinstance(data_or_node, Node):

item = data_or_node

else:

item = Node(data_or_node)

if not self.head:

self.head = item

self.length += 1

else:

node = self.head

while node.next:

node = node.next

node.next = item

node.prev = node

self.length += 1

def insert(self, index, data_or_node):

if self.is_empty():

print("this link list is empty.")

return

if self.is_empty() or index < 0 or index >= self.length:

print("error:out of index.")

return

item = None

if isinstance(data_or_node, Node):

item = data_or_node

else:

item = Node(data_or_node)

if index == 0:

item.next = self.head

self.head = item

self.length += 1

return

if index == 0:

item.next = self.head

self.head.prev = item

self.head = item

self.length += 1

return

node = self.head

while node.next and index:

node = node.next

index -= 1

if not index:

pre_node = node.pre

pre_node.next = item

item.prev = pre_node

item.next = node

node.prev = item

self.length += 1

循环链表(Circular Linked list)

循环链表与双向链表相似,不同的地方在于:在链表的尾部增加一个指向头结点的指针,头结点也增加一个指向尾节点的指针,以及第一个节点指向头节点的指针,从而更方便索引链表元素。

关于链表的面试题比较多样化,常见的有:

1、单链表的创建和遍历

2、求单链表中节点的个数

3、查找单链表中的倒数第k个结点(剑指offer,题15)

4、查找单链表中的中间结点

5、合并两个有序的单链表,合并之后的链表依然有序【出现频率高】(剑指offer,题17)

6、单链表的反转【出现频率最高】(剑指offer,题16)

class ReverseLinkList:

"""

反转链表

"""

def __init__(self, linklist, head):

self.linklist = linklist

self.head = head

def reverse_linklist(self):

if not self.linklist or self.linklist.next is None:

return self.linklist

node = self.head.next

self.head.next = None

pre_node = self.head

while not node:

next_node = node.next

node.next = pre_node

pre_node = node

node = next_node

return pre_node

7、从尾到头打印单链表(剑指offer,题5)

8、判断单链表是否有环

9、取出有环链表中,环的长度

10、单链表中,取出环的起始点(剑指offer,题56)。本题需利用上面的第8题和第9题。

11、判断两个单链表相交的第一个交点(剑指offer,题37)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值