python实现链表(单向链表以及双向链表)

单向链表也是一种非常基本的数据结构,跟列表比较起来,它的内存不连续,在实际应用中场景还是多于列表的,列表之所以使用的场景多于链表无外乎以下几个原因:

1、列表是python内置的数据结构,可以直接使用;链表需要我们自己去设计

2、列表作为内置数据类型,为我们隐藏了实现细节,只是暴露了几个操作它的api(append、remove、pop、[start:stop]等),我们不用去关心底层实现,只关注业务即可;链表每个操作方法需要我们自己去设计

3、数据量比较少的话,列表的内存开销还是要小于链表的,python的链表元素其实是一个个实例化的对象,一般来说内存开销是大于列表的(内存开销测试具体没试验过,个人臆测)

需要自己去设计实现,这个对于python开发者来说就比较难受了,一般都会倾向于直接使用列表而不使用数组。

但是链表也有链表的好处

1、对于内存以及程序响应都比较好,对于python程序来说,声明一个列表,多数情况下都是往里面添加元素的多,这就需要这个列表需要不断地申请扩大内存,不断扩充总会到达边界,这时python就会创建一个链表去链接另外一片比较大的连续内存,这不是一个好的编程习惯,很容易发生内存溢出以及内存泄漏,再者删除指定位置元素还涉及数据元素下标更新的处理,会增加程序的响应时间,顺序添加时间响应还好,要是从头开始插入的话,时间复杂度是O(N2)。

import time

lst1 = list()
lst2 = list()


def cal_time(func):
    def wrapper(*args, **kwargs):
        t1 = time.time()
        result = func(*args, **kwargs)
        t2 = time.time()
        print("%s running time: %s secs." % (func.__name__, t2 - t1))
        return result

    return wrapper

# O(n2)
def append_data_from_head(num):
    lst1.insert(0, num)

# o(n)
def append_data_from_tail(num):
    lst1.append(num)


@cal_time
def get_result(times):
    for el in range(times):
        append_data_from_head(el)


@cal_time
def get_result1(times):
    for el in range(times):
        append_data_from_tail(el)


get_result(10000)
get_result1(10000)

 1000个数的时间如下

 1万个数的时间就成了下面的图(响应时间4秒,也就是比如客户添加一个宝贝到购物车,4分钟之后显示添加成功,估计会直接卸载这个应用)

 而链表的更新以及插入数据的时间复杂度是O(N),其时间和append的时间差不多

2、减少内存碎片产生的可能性,列表是申请的连续内存,如果存储的对象大小不一致,当删除一个元素,下一个元素填补就可能存在使用不了的内存碎片

废话不再多说,直接上代码:

1、单向链表以及增删改查方法

  1 # 初始化节点,添加值以及指针属性
  2 class Node:
  3     def __init__(self, value, next_=None):
  4         self.value = value
  5         self.next_ = next_
  6 
  7     # 可以直接获取到指定节点的值
  8     def get_data(self):
  9         return self.value
 10 
 11     # 直接设置获取到的节点的值
 12     def set_new_data(self, new_value):
 13         self.value = new_value
 14 
 15 
 16 # 定义链表的类
 17 class LinkList(object):
 18     # 初始化头部节点并且初始化长度
 19     def __init__(self, head=None):
 20         self.head = head
 21         if self.head:
 22             self.length = 1
 23         else:
 24             self.length = 0
 25 
 26     # 获取头部节点
 27     def get_head(self):
 28         return self.head
 29 
 30     # 判断链表是否为空链表
 31     def is_empty(self):
 32         if not self.length:
 33             return True
 34         return False
 35 
 36     # 添加新节点
 37     def append_node(self, data_or_node):
 38         # 判断是否是节点的实例
 39         if isinstance(data_or_node, Node):
 40             item = data_or_node
 41         else:
 42             item = Node(data_or_node)
 43         # 判断是不是空链表,当然也可以通过is_empty来判断
 44         if not self.head:
 45             self.head = item
 46             self.length += 1
 47         else:
 48             node = self.head  # 头结点始终保持不变
 49             # 遍历链表,找到最后一个节点
 50             while node.next_:
 51                 node = node.next_
 52             # 找到并且赋值
 53             node.next_ = item
 54             self.length += 1
 55 
 56     # 删除节点,传入下标
 57     def delete_node(self, index):
 58         if self.is_empty():
 59             print("this link list is empty.")
 60             return
 61         if index < 0 or index >= self.length:
 62             print("error: out of index.")
 63             return
 64         # 下标为0,直接设置头节点的下一个节点为头部节点同时长度减一
 65         if index == 0:
 66             self.head = self.head.next_
 67             self.length -= 1
 68         # 一般的节点,需要找到下标的前一个子节点以及后一个子节点,然后直接连接起来,丢掉下标所在的节点
 69         node = self.head
 70         pre = self.head
 71         # 定位找到下标所在的节点
 72         while node.next_ and index:
 73             # 先确定前一个子节点,之后是往后找下一个子节点
 74             pre = node
 75             node = node.next_
 76             index -= 1
 77         if not index:
 78             # 找到了,前一个子节点的下一个指针连接当前节点的下一个节点同时长度减一
 79             pre.next_ = node.next_
 80             self.length -= 1
 81 
 82     def update_node(self, index, value):
 83         if self.is_empty():
 84             print("this link list is empty.")
 85             return
 86         if index < 0 or index >= self.length:
 87             print("error: out of index")
 88             return
 89         node = self.head
 90         while node.next_ and index:
 91             node = node.next_
 92             index -= 1
 93         if not index:
 94             node.value = value
 95 
 96     def get_node(self, index):
 97         if self.is_empty():
 98             print("this link list is empty.")
 99             return
100         if index < 0 or index >= self.length:
101             print("error: out of index.")
102         node = self.head
103         while node.next_ and index:
104             node = node.next_
105             index -= 1
106         if not index:
107             return node.value
108 
109     def get_index(self, value):
110         if self.is_empty():
111             print("this link list is empty.")
112             return
113         node = self.head
114         j = 0
115         while node:
116             if node.value == value:
117                 return j
118             else:
119                 node = node.next_
120                 j += 1
121         if j == self.length:
122             print("%s not found." % value)
123             return
124 
125     def insert_node(self, index, data_or_node):
126         if self.is_empty():
127             print("this link list is empty.")
128             return
129         if index < 0 or index >= self.length:
130             print("error: out of index.")
131             return
132         if isinstance(data_or_node, Node):
133             item = data_or_node
134         else:
135             item = Node(data_or_node)
136         if index == 0:
137             item.next_ = self.head
138             self.head = item
139             self.length += 1
140         node = self.head
141         pre = self.head
142         while node.next_ and index:
143             pre = node
144             node = node.next_
145             index -= 1
146         if not index:
147             pre.next_ = item
148             item.next_ = node
149             self.length += 1
150 
151     def clear(self):
152         self.head = None
153         self.length = 0
154 
155 
156 link_list = LinkList()
157 # 新增一个节点
158 link_list.append_node(0)
159 # 获取节点值
160 node_0_val = link_list.get_node(0)
161 print(node_0_val, link_list.length)  # 0 1
162 # 获取值为0的数据的位置
163 node_0_index = link_list.get_index(0)
164 print(node_0_index)  # 0
165 link_list.append_node(1)
166 link_list.append_node(1)
167 link_list.append_node(4)
168 link_list.append_node(5)
169 print(link_list.length)  # 5
170 # 遍历所有数据
171 for el in range(link_list.length):
172     print(link_list.get_node(el))  # 0 1 1 4 5
173 
174 # 插入一个数据
175 link_list.insert_node(3, 3)
176 # 遍历所有数据
177 for el in range(link_list.length):
178     print(link_list.get_node(el))  # 0 1 1 3 4 5
179 
180 # 修改一个数据
181 link_list.update_node(2, 2)
182 print(">" * 10)
183 for el in range(link_list.length):
184     print(link_list.get_node(el))  # 0 1 2 3 4 5
185 
186 # 删除一个节点
187 link_list.delete_node(4)
188 print("<" * 10)
189 for el in range(link_list.length):
190     print(link_list.get_node(el))  # 0 1 2 3 5
View Code

2、双向链表以及增删改查方法

  1 class Node(object):
  2     def __init__(self, value, p=None):
  3         self.data = value
  4         self.next = p
  5         self.prev = p
  6 
  7     def get_data(self):
  8         return self.data
  9 
 10     def set_new_data(self, new_value):
 11         self.value = new_value
 12 
 13 
 14 class Linklist(object):
 15     def __init__(self, head=None):
 16         self.head = head
 17         if self.head:
 18             self.length = 1
 19         else:
 20             self.length = 0
 21 
 22     def is_empty(self):
 23         if not self.length:
 24             return True
 25         return False
 26 
 27     def append(self, data_or_node):
 28         if isinstance(data_or_node, Node):
 29             item = data_or_node
 30         else:
 31             item = Node(data_or_node)
 32         if not self.head:
 33             self.head = item
 34             self.length += 1
 35         else:
 36             node = self.head
 37             while node.next:
 38                 node = node.next
 39             node.next = item
 40             item.prev = node
 41             self.length += 1
 42 
 43     def insert(self, index, data_or_node):
 44         if self.is_empty():
 45             print("this link list is empty.")
 46             return
 47         if index < 0 or index >= self.length:
 48             print("error: out of index")
 49             return
 50         if isinstance(data_or_node, Node):
 51             item = data_or_node
 52         else:
 53             item = Node(data_or_node)
 54         if index == 0:
 55             item.next = self.head
 56             self.head.prev = item
 57             self.head = item
 58             self.length += 1
 59         node = self.head
 60         while node.next and index:
 61             node = node.next
 62             index -= 1
 63         if not index:
 64             # 先找到当前节点的前一个节点,之后是先创建前指向当前节点的指针,然后当前节点指向前一个节点的指针
 65             pre_node = node.prev
 66             pre_node.next = item
 67             item.prev = pre_node
 68             item.next = node
 69             node.prev = item
 70             self.length += 1
 71             #
 72 
 73     def update_node(self, index, value):
 74         if self.is_empty():
 75             print("this link list is empty.")
 76             return
 77         if index < 0 or index >= self.length:
 78             print("error: index out of range.")
 79             return
 80         if index == 0:
 81             self.head.set_new_data(value)
 82         node = self.head
 83         while node.next and index:
 84             node = node.next
 85             index -= 1
 86         if not index:
 87             node.set_new_data(value)
 88 
 89     def delete_node(self, index):
 90         if self.is_empty():
 91             print("this link list is empty.")
 92             return
 93         if index < 0 or index >= self.length:
 94             print("error: index out of range.")
 95             return
 96         if index == 0:
 97             self.head = self.head.next
 98             self.head.prev = None
 99             self.length -= 1
100             return
101         prev_node = self.head
102         node = self.head
103         while node.next and index:
104             prev_node = node.prev
105             node = node.next
106             index -= 1
107         if not index:
108             # 需要连接两次,分别是当前位置前一个节点连接后面的一个节点,后面的一个节点连接前一个节点,当前节点断了prev和next
109             post_node = node.next
110             prev_node.next = post_node
111             post_node.prev = prev_node
112             node.prev = None
113             node.next = None
114             self.length -= 1
115 
116     def get_node(self, index):
117         node = self.head
118         while node.next and index:
119             # print(node.next, index)
120             node = node.next
121             index -= 1
122         print(node.get_data())
123         return node.get_data()
124 
125     def get_pre_node(self, index):
126         if index == 0:
127             return
128         else:
129             node = self.head
130             while node.next and index:
131                 node = node.next
132                 index -= 1
133             if not index:
134                 node = node.prev
135                 print(node.get_data())
136                 return node.get_data()
137 
138 
139 link_lst = Linklist()
140 link_lst.append(0)
141 link_lst.append(1)
142 link_lst.append(2)
143 link_lst.append(4)
144 link_lst.append(5)
145 link_lst.insert(3, 3)
146 link_lst.get_node(0)
147 link_lst.get_node(1)
148 link_lst.get_node(2)
149 link_lst.get_node(3)
150 link_lst.get_node(4)
151 link_lst.get_node(5)
152 
153 print("删除节点")
154 link_lst.delete_node(2)
155 
156 link_lst.get_node(0)
157 link_lst.get_node(1)
158 link_lst.get_node(2)
159 link_lst.get_node(3)
160 print(">" * 100)
161 link_lst.get_pre_node(0)
162 print(">" * 10)
163 link_lst.get_pre_node(1)
164 print(">" * 10)
165 link_lst.get_pre_node(2)
166 print(">" * 10)
167 link_lst.get_pre_node(3)
168 print(">" * 10)
View Code

待优化项的是尾部新增一个节点的时间复杂度从O(n)简化到O(1)。

猜你喜欢

转载自blog.csdn.net/bruce_van/article/details/126073926