python实现链表操作_单链表所有操作38种methods之Python实现

# coding:utf-8

class Node(object):

'''

elem: 节点保存的数据

next: 保存下一个节点对象

'''

def __init__(self,

init_elem=-1, pnext=None):

self.elem = init_elem

self.next = pnext

class SingleLinkedList(object):

def

__init__(self):

self._head = None

def

is_empty(self):

return not self._head

def append(self,

elem):

node = Node(elem)

if not self._head: # 若链表为空,head指向新节点

self._head

= node

else: #

否则,循环到链表末尾,指向新节点

cur =

self._head

while

cur.next:

cur = cur.next

cur.next =

node

def add(self,

elem): # 从头加

node = Node(elem)

node.next = self._head

self._head = node

def

traverse(self):

cur = self._head

L = []

while cur:

L.append(cur.elem)

cur =

cur.next

print(L)

def len(self):

cur = self._head

i = 0

while cur:

cur =

cur.next

i +=

1

return i

def is_in(self,

elem):

cur = self._head

while cur:

if

cur.elem == elem:

return True

cur =

cur.next

return False

def count(self,

elem):

cur = self._head

cnt = 0

while cur:

if

cur.elem == elem:

cnt += 1

cur =

cur.next

return cnt

def index(self,

elem):

cur = self._head

i = 0

while cur:

if

cur.elem == elem:

return i

cur =

cur.next

i +=

1

return 'Not Found!'

def indices(self,

elem):

cur = self._head

i = 0

L = []

while cur:

if

cur.elem == elem:

L.append(i)

cur =

cur.next

i +=

1

return L

# 获得指定位置节点的值

def get_value(self,

index):

if not self._head:

return

'Empty List!'

elif index < 0:

return

'List index (%s) out of range!' % index

else:

cur =

self._head

for i in

range(index):

if cur.next:

cur = cur.next

else:

return 'List index (%s) out of range!' %

index

return

cur.elem

#

有了len()之后,get_value的另一种方法。index允许为负值

# 但调了len(), Time

Complexity就变O(2n)了

def get_value_1(self,

index):

n = self.len()

if not self._head:

return

'Empty List!'

elif index < -n or index >= n:

return

'List index (%s) out of range!' % index

else:

if index

< 0:

index += n

cur =

self._head

cnt =

0

while cnt

< index:

cur = cur.next

cnt += 1

return

cur.elem

# 更新指定位置节点的值

def update(self, index,

value):

if not self._head:

print('Empty List!')

elif index < 0:

print('List index (%s) out of range!' % index)

else:

cur =

self._head

for i in

range(index):

if cur.next:

cur = cur.next

else:

print('List index (%s) out of range!' %

index)

return

cur.elem =

value

#

有了len()之后,update的另一种方法。index允许为负值

# 但调了len(), Time

Complexity就变O(2n)了

def update_1(self,

index, value):

n = self.len()

if not self._head:

print('Empty List!')

elif index < -n or index >= n:

print('List index (%s) out of range!' % index)

else:

if index

< 0:

index += n

cur =

self._head

cnt =

0

while cnt

< index:

cur = cur.next

cnt += 1

cur.elem =

value

# 删元素,有多个只删第一个

def remove(self,

elem):

hasRemoved = False

if not self._head:

print('Empty List!')

else:

if

self._head.elem == elem: # 首元素

self._head =

self._head.next

hasRemoved = True

else: # 非首元素

prev =

self._head # prev将指向待删节点的前一个位置

while prev.next and

hasRemoved is False:

if prev.next.elem == elem:

prev.next

= prev.next.next # 删除prev指向节点的下一个

hasRemoved

= True

else:

prev =

prev.next

if

hasRemoved:

print('The 1st \'%s\' was

removed.' % elem)

else:

print('Not Found!')

# 删除所有值为elem的节点

def remove_all(self,

elem):

hasRemoved = False

cnt = 0

if not self._head:

print('Empty List!')

else:

#

目标元素位于首部,删之

while

self._head and self._head.elem == elem:

self._head =

self._head.next

hasRemoved = True

cnt += 1

#

删完首部的目标元素,继续寻而删之

if

self._head:

prev =

self._head # prev将指向待删节点的前一个位置

while prev.next:

if prev.next.elem == elem:

prev.next

= prev.next.next

hasRemoved

= True

cnt +=

1

continue

else:

prev =

prev.next

if

hasRemoved is True:

print('%s \'%s\'(s) were

removed.' % (cnt, elem))

else:

print('Not Found!')

# 删index

def delete(self,

index):

if not self._head:

print('Empty List!')

elif index < 0:

print('List index (%s) out of range!' % index)

else:

if 0 ==

index:

self._head =

self._head.next

print('The 0th element was

removed.')

else:

prev =

self._head #

prev将指向位置index-1的节点

if not prev.next:

# 若index不为0, 节点数必须多于1

print('List index (%s) out of range!' %

index)

return

# 用一般for循环:

for i in range(index -

1):

if prev.next.next:

prev =

prev.next

else:

print('List index (%s) out of range!' % index)

return

# 此时prev已指向了index-1

prev.next =

prev.next.next # 删之

print('The %s. element was

removed.' % index)

# 用for-else语句:

# for i in range(index -

1):

# if not prev.next.next:

# print('List index (%s) out of range!' %

index)

# break

# else:

# prev = prev.next

# # 此时prev已指向了index-1

# else:

# #

for循环未被break中断(未超出范围),执行删除操作

# prev.next =

prev.next.next

# print('The %s. element was

removed.' % index)

#

有了len()之后,删index的另一种方法。index允许为负值

# 但调了len(), Time

Complexity就变O(2n)了

def delete_1(self,

index):

n = self.len()

if not self._head:

print('Empty List!')

elif index < -n or index >= n:

print('List index (%s) out of range!' % index)

else:

if index

< 0:

index += n

if 0 ==

index:

self._head =

self._head.next

print('The 0th element was

removed.')

else:

prev = self._head

cnt = 1

while cnt < index:

prev = prev.next

cnt += 1

# 移到了,prev指向了index-1.

删之

prev.next =

prev.next.next

print('The %s. element was

removed.' % index)

def clear(self):

self._head = None

# 浅拷贝,只共享指针

def copy(self):

new_linked_list = SingleLinkedList()

new_linked_list._head = self._head

return new_linked_list

def extend(self,

list_b):

if not self._head: #

若自己是空链表

self._head

= list_b._head

else:

cur_a =

self._head

while

cur_a.next:

cur_a = cur_a.next

cur_a.next

= list_b._head

return self._head

# 统计元素分布

def

histogram(self):

cur = self._head

dict = {}

while cur:

dict[cur.elem] = dict.setdefault(cur.elem, 0) + 1

cur =

cur.next

print(dict)

# 去重

def

distinct(self):

if self._head and

self._head.next: # 节点数多于1才需要去重

prev =

self._head

L =

[self._head.elem]

while

prev.next:

if prev.next.elem not in

L:

L.append(prev.next.elem)

prev = prev.next

else:

prev.next = prev.next.next #

删掉prev指向的节点的下一个

# 指定位置前插入节点

def insert(self, pos,

elem):

if not self._head or pos <= 0:

# 空链表 或

插入位置小于等于0

self.add(elem)

else:

prev =

self._head # prev将指向位置pos-1的节点

#

用一般for循环:

for i in

range(pos - 1):

if prev.next:

prev = prev.next

else:

self.append(elem)

return

node =

Node(elem)

node.next

= prev.next

prev.next

= node

#

用for-else语句:

# for i in

range(pos - 1):

# if not

prev.next:

# self.append(elem)

# break

# else:

# prev = prev.next

#

else:

# #

for循环未被break中断(未超出范围),执行删除操作

# node =

Node(elem)

# node.next

= prev.next

# prev.next

= node

#

有了len()之后,insert的另一种方法。index允许为负值

# 但调了len(), Time

Complexity就变O(2n)了

def insert_1(self, pos,

elem):

n = self.len()

if not self._head or pos <= -n or 0 ==

pos:

# 空链表 或

插入位置小于等于-n或等于0

self.add(elem)

elif pos >= n:

#

位置超出末位

self.append(elem)

else:

if pos

< 0:

pos += n

node =

Node(elem)

prev =

self._head # prev将指向位置pos-1的节点

cnt =

1

while cnt

< pos:

prev = prev.next

cnt += 1

node.next

= prev.next

prev.next

= node

#

仿pop:返回第index个值,并将之从链表中删除;

#

若index缺省,则返回链表尾部的值,并删之

def pop(self,

index=-1):

if not self._head:

print('Empty List!')

elif index < -1:

print('List index (%s) out of range!' % index)

else:

if 0 ==

index:

# 弹第一个

res = self._head.elem

self._head =

self._head.next

return res

elif -1 ==

index:

# 弹最后一个

#

其实无需区别操作最后一个和中间节点,只是index为-1时for循环终止条件不好写

if not self._head.next:

# 只有一个节点

res = self._head.elem

self._head = None

return res

else:

# 节点数多于1

prev = self._head

while prev.next.next:

prev =

prev.next

res = prev.next.elem

prev.next = None

return res

else:

# 弹中间元素

prev =

self._head # prev将指向位置index-1的节点

if not prev.next:

# 若index不为0或-1, 节点数必须多于1

print('List index (%s) out of range!' %

index)

return

# 用一般for循环:

for i in range(index -

1):

if prev.next.next:

prev =

prev.next

else:

print('List index (%s) out of range!' % index)

return

# 此时prev已指向了待弹元素的前一位

res = prev.next.elem

prev.next =

prev.next.next # 删之

return res

# 用for-else语句:

# for i in range(index -

1):

# if not prev.next.next:

# print('List index (%s) out of range!' %

index)

# break

# else:

# prev = prev.next

# # 此时prev已指向了待弹元素的前一位

# else:

# #

for循环未被break中断(未超出范围),执行删除操作

# res = prev.next.elem

# prev.next =

prev.next.next

# return res

#

有了len()之后,pop的另一种方法。index允许为-1以外的负值

# 但调了len(), Time

Complexity就变O(2n)了

def pop_1(self,

index=-1):

n = self.len()

if not self._head:

print('Empty List!')

elif index < -n or index >= n:

print('List index (%s) out of range!' % index)

else:

if index

< 0:

index += n

if 0 ==

index:

# 弹第一个

res = self._head.elem

self._head =

self._head.next

return res

else:

# 弹中间元素或末尾元素

prev =

self._head # prev将指向位置index-1的节点

cnt = 1

while cnt < index:

prev = prev.next

cnt += 1

# 此时prev已指向了待弹元素的前一位

res = prev.next.elem

prev.next =

prev.next.next # 删之

return res

# 百分位数。0.25: 第一四分位数;0.5:

中位数;0.75: 第三四分位数

def percentile(self,

percent):

if not self._head:

return

'Empty List!'

if percent < 0 or percent > 1:

return

'The Percent must be between 0 and 1!'

cur = self._head

L = []

i = 0

while cur:

L.append(cur.elem)

cur =

cur.next

i +=

1

L.sort() # 为避免改变原链表顺序,不应对原链表排序

if 1 == percent: # percent为1时,L[int(percent * i)]会越界

return

L[-1]

else:

return

L[int(percent * i)]

def swap(self, i,

j):

t = self.get_value(j)

self.update(j, self.get_value(i))

self.update(i, t)

def

bubble_sort(self):

for i in range(self.len())[::-1]:

for j in

range(i):

if self.get_value(j) >

self.get_value(j + 1):

self.swap(j, j + 1)

def

insertion_sort(self):

for i in range(1, self.len()):

#

把[i]插入已排好的[:i]中

k =

i

for j in

range(i - 1, -1, -1): # 从i-1到0

if self.get_value(k) <

self.get_value(j):

self.swap(k, j)

k -= 1

# 如发生交换,指针k因为要始终指向待插元素[i], 也得一路前移

def quick_sort(self,

left, right):

i = left

j = right

if i >= j:

return

key = self.get_value(i)

while i < j:

while i

< j and self.get_value(j) >= key:

j -= 1

self.swap(i, j)

while i

< j and self.get_value(i) <= key:

i += 1

self.swap(j, i)

self.update(i, key)

self.quick_sort(left, i - 1)

self.quick_sort(j + 1, right)

# 返回链表中点的指针

def get_mid(self,

head):

if not head:

return

head

fast = slow = head

while fast.next and fast.next.next:

slow =

slow.next

fast =

fast.next.next

return slow

def merge_sort(self,

head):

if not head or not head.next:

return

head

mid = self.get_mid(head)

left = head

right = mid.next

mid.next = None #

从中间截断链表

left = self.merge_sort(left)

right = self.merge_sort(right)

self._head = self.merge(left, right)

'''

要将原链表的头指针(self._head)改为排序后链表的头指针(使其指

向最小元素)。链表merge sort的本质是改变一系列指针的指向(这

点和quick sort互换一系列节点的动作不同,由于quick sort未动指

针,所以原链表的头指针不用改)。如果每次merge后头指针还指

向原始头元素,经过一次指针重构后,头指针就可能指向中部的

某元素,最后traverse就可能只打印出原始头元素及其排序后的后

续元素。故而需要将链表头指针始终指向排序后的首元素,并返

回这个新的头指针。

'''

return self._head

def merge(self, p,

q):

tmp = Node(-1)

h = tmp

while p and q:

if p.elem

< q.elem:

h.next = p

p = p.next

else:

h.next = q

q = q.next

h =

h.next

if p:

h.next =

p

if q:

h.next =

q

return tmp.next

def reverse(self):

if self._head and

self._head.next: #

节点数多于1才有反转的意义

cur =

self._head

newHead =

None

while

cur:

# post关键了!如果直接修改cur.next,

没有了指向下一节点的引用,链表就断了

post = cur.next

cur.next = newHead

newHead = cur

cur = post

self._head

= newHead

# 用递归

def reverse_1(self,

head):

if not head or not head.next: # 节点数多于1才有反转的意义

return

head

newHead = self.reverse_1(head.next)

head.next.next = head

head.next = None

self._head = newHead

return self._head

# 检测是否有环

# 返回一个Tuple, [0]: True /

False; [1]: 环的入口;[2]: 环长

def

has_circle(self):

if not self._head:

print('Empty List!')

return

False, -1, 0

fast = slow = self._head

while fast.next and fast.next.next:

slow =

slow.next

fast =

fast.next.next

if slow ==

fast:

# 快慢指针相遇,有环。下面找环的入口

slow = self._head

entr = 0

while slow != fast:

slow = slow.next

fast = fast.next

entr += 1

# slow停下,fast再走一圈,数出环长

fast = fast.next

c = 1

while slow != fast:

fast = fast.next

c += 1

return True, entr, c

return False, -1, 0

def

break_circle(self):

circle_info = self.has_circle()

if circle_info[0]: # 有环

cur =

self._head

i =

0

while i

< circle_info[1] + circle_info[2] - 1:

cur = cur.next

i += 1

#

此时cur指向“末节点”

cur.next =

None

print('Circle Broken.')

else:

print('No

Circle!')

if __name__ == '__main__':

myLinkedList =

SingleLinkedList()

myLinkedList.append(1)

print('Is empty: ',

myLinkedList.is_empty())

myLinkedList.add(2)

myLinkedList.append(2)

myLinkedList.add(1)

myLinkedList.append(3)

myLinkedList.append(6)

myLinkedList.traverse()

print('Length:',

myLinkedList.len())

print('Is 3 in the list:

', myLinkedList.is_in(3))

print('The num of 1: ',

myLinkedList.count(1))

print('The index of 2:

', myLinkedList.index(2))

print('The indices of

2s: ', myLinkedList.indices(2))

print('The 1. elem: ',

myLinkedList.get_value(1))

print('The -1. elem: ',

myLinkedList.get_value_1(-1))

myLinkedList.update(1,

1)

myLinkedList.update_1(-1, 3)

myLinkedList.traverse()

myLinkedList.remove(1)

myLinkedList.traverse()

myLinkedList.remove_all(1)

myLinkedList.traverse()

myLinkedList.delete(1)

myLinkedList.traverse()

myLinkedList.delete_1(-1)

myLinkedList.traverse()

myLinkedList.clear()

print('Is empty: ',

myLinkedList.is_empty())

aList =

SingleLinkedList()

aList.append(1)

aList.append(3)

myLinkedList =

aList.copy()

myLinkedList.traverse()

bList =

SingleLinkedList()

bList.append(1)

bList.append(4)

myLinkedList.extend(bList)

myLinkedList.traverse()

myLinkedList.histogram()

myLinkedList.distinct()

myLinkedList.traverse()

myLinkedList.insert(0,

0)

myLinkedList.insert_1(-2, 2)

myLinkedList.traverse()

print('The 1st quartile:

', myLinkedList.percentile(0.25))

print('The 3th quartile:

', myLinkedList.percentile(0.75))

print('The popped elem:

', myLinkedList.pop(1))

print('The popped elem:

', myLinkedList.pop())

print('The popped elem:

', myLinkedList.pop_1())

print('The popped elem:

', myLinkedList.pop_1(-1))

myLinkedList.traverse()

myLinkedList.add(1)

myLinkedList.add(2)

myLinkedList.add(3)

myLinkedList.bubble_sort()

myLinkedList.traverse()

myLinkedList.reverse()

myLinkedList.insertion_sort()

myLinkedList.traverse()

myLinkedList.reverse_1(myLinkedList._head)

myLinkedList.quick_sort(0, myLinkedList.len() - 1)

myLinkedList.traverse()

myLinkedList.reverse_1(myLinkedList._head)

myLinkedList.merge_sort(myLinkedList._head)

myLinkedList.traverse()

node0 = Node(0)

node1 = Node(1)

node2 = Node(2)

node3 = Node(3)

node4 = Node(4)

node5 = Node(5)

cList =

SingleLinkedList()

cList._head =

node0

node0.next = node1

node1.next = node2

node2.next = node3

node3.next = node4

node4.next = node5

node5.next = node2

print(cList.has_circle())

cList.break_circle()

cList.traverse()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值