程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Data structure Python Version (II) - linked list

編輯:Python

Catalog

  • One 、 What is a linked list ?
  • Two 、 Single chain list
    • 2.1 Linked list node class and linked list class
    • 2.2 Create a single linked list from an array
      • 2.2.1 The first interpolation
      • 2.2.2 The tail interpolation
    • 2.3 Implementation of linear table operation in single linked list
      • 2.3.1 The search sequence number is i i i The node of
      • 2.3.2 Add the element to the end of the single linked list
      • 2.3.3 Insert elements
      • 2.3.4 Remove elements
      • 2.3.5 Get elements
      • 2.3.6 Set the element
      • 2.3.7 Find the first one as e The serial number of
      • 2.3.8 Get the length of single linked list
      • 2.3.9 Print single linked list
  • 3、 ... and 、 Double linked list
    • 3.1 Linked list node class and linked list class
    • 3.2 Create a double linked list from an array
      • 3.2.1 The first interpolation
      • 3.2.2 The tail interpolation
    • 3.3 Some implementation of double linked list
      • 3.3.1 Insert elements
      • 3.3.2 Remove elements
  • Four 、 Circular linked list
    • 4.1 Circular single chain table
    • 4.2 Circular double linked list
  • 5、 ... and 、 Comparison between sequential list and linked list
    • 5.1 Space based considerations
    • 5.2 For the sake of time
  • 6、 ... and 、LeetCode actual combat
    • 6.1 LeetCode#27—— Remove elements
      • Method 1 : Double pointer
      • Method 2 : Double pointer optimization
    • 6.2 LeetCode#26—— Delete duplicates in sort array
    • 6.3 LeetCode#80—— Delete duplicates in sort array II
    • 6.4 LeetCode#4—— Find the median of two ordered arrays
    • 6.5 LeetCode#21—— Merge two ordered lists
      • Method 1 : iteration
      • Method 2 : recursive
    • 6.6 LeetCode#83—— Delete duplicate elements from the sort list
    • 6.7 LeetCode#203—— Remove linked list elements
    • 6.8 LeetCode#19—— Delete the last of the linked list n Nodes
    • 6.9 LeetCode#234—— Palindrome list
    • 6.10 LeetCode#61—— Rotate the list
  • 7、 ... and 、 appendix
    • 7.1 Single linked list complete code
    • 7.2 Double linked list complete code

One 、 What is a linked list ?

The linked storage structure of a linear table is called Linked list . Each node in the linked list contains not only the information of the element itself , It also contains information about the logical relationship between elements , That is, a node contains the address information of the successor node or the address information of the predecessor node , be called The pointer attribute . In this way, the successor node or precursor node can be easily found through the pointer attribute of a node .

If each node only sets a pointer attribute to its subsequent nodes , Such a linked list is called single ( towards ) Linked list . If each node sets two pointer attributes , It is used to point to its predecessor node and successor node respectively , Such a linked list is called double ( towards ) Linked list . As shown in the figure below :

The corresponding pointer attribute of no predecessor node or successor node is used None Express .

In order to insert and delete nodes in the linked list , Usually, the linked list has a head node , And uniquely identify the linked list through the node pointer .

Will usually p p p The node pointed to is called p p p Node or node p p p, The head node is head The linked list is called head Linked list . No data elements are stored in the header node ( An empty table is a linked list that contains only header nodes ). Generally, the length of the linked list does not count the head node , It only refers to the number of data nodes .

Two 、 Single chain list

2.1 Linked list node class and linked list class

To realize single linked list , We need to create linked list node classes and linked list classes , as follows :

class LinkNode:
def __init__(self, data=None):
self.data = data # Storing data , The default is None, That is, there is no data 
self.next = None # The pointer , Used to point to the next node 
class LinkList:
def __init__(self):
self.head = LinkNode() # The header node does not contain data , Therefore, no parameters are passed 
self.head.next = None # When initializing a linked list , The result is an empty linked list 

2.2 Create a single linked list from an array

2.2.1 The first interpolation

The method starts with an empty table , Keep reading arrays a a a And generate a new node s s s, then s s s Insert it into the header of the linked list .

def fromlist(self, a):
for i in range(len(a)):
s = LinkNode(a[i])
s.next = self.head.next
self.head.next = s

Time complexity O ( n ) \mathcal{O}(n) O(n), n n n by a a a The number of elements in .

Obvious , The linked list established by head inserting method , The data sequence is the same as a a a The order in is completely opposite .

2.2.2 The tail interpolation

If you want the data order in the linked list to be consistent with the original array , Tail interpolation can be used . To do this, you need to add a tail pointer t t t, Make it always point to the end of the current list .

def fromlist(self, a):
t = self.head
for i in range(len(a)):
s = LinkNode(a[i])
t.next = s
t = s
t.next = None

Time complexity O ( n ) \mathcal{O}(n) O(n).

2.3 Implementation of linear table operation in single linked list

In order to realize the correlation operation of linear table in single linked list , We first need to implement a function , That is, the search sequence number is i i i The node of .

2.3.1 The search sequence number is i i i The node of

def geti(self, i):
p = self.head # Traverse from the beginning of the node 
j = -1 # Because the index of the next node pointed by the head node is 0
while j < i and p is not None:
p = p.next
j += 1
return p

Time complexity O ( n ) \mathcal{O}(n) O(n).

2.3.2 Add the element to the end of the single linked list

def add(self, e):
p = self.head
s = LinkNode(e)
while p.next is not None:
p = p.next
p.next = s

Time complexity O ( n ) \mathcal{O}(n) O(n).

2.3.3 Insert elements

To insert an element, follow these steps :

def insert(self, i, e):
assert i >= 0
p = self.geti(i - 1)
assert p is not None
s = LinkNode(e)
s.next = p.next
p.next = s

Time complexity O ( n ) \mathcal{O}(n) O(n).

2.3.4 Remove elements

To delete an element, follow these steps :

def delete(self, i):
assert i >= 0
p = self.geti(i - 1)
assert p is not None and p.next is not None
p.next = p.next.next

Time complexity O ( n ) \mathcal{O}(n) O(n).

2.3.5 Get elements

def __getitem__(self, i):
assert i >= 0
p = self.geti(i)
assert p is not None
return p.data

Time complexity O ( n ) \mathcal{O}(n) O(n).

2.3.6 Set the element

def __setitem__(self, i, x):
assert i >= 0
p = self.geti(i)
assert p is not None
p.data = x

Time complexity O ( n ) \mathcal{O}(n) O(n).

2.3.7 Find the first one as e The serial number of

def getno(self, e):
p = self.head.next
k = 0
while p is not None and p.data != e:
p = p.next
k += 1
return -1 if p is None else k # Return... When not found -1

Time complexity O ( n ) \mathcal{O}(n) O(n).

2.3.8 Get the length of single linked list

def getsize(self):
p = self.head.next
j = 1
while p.next is not None:
p = p.next
j += 1
return j

Time complexity O ( n ) \mathcal{O}(n) O(n).

2.3.9 Print single linked list

Printing a single linked list means printing all the data elements in it .

def display(self):
p = self.head.next
while p.next is not None:
print(p.data, end=' ')
p = p.next
print(p.data)

This printing method can ensure that the characters after the last number are not spaces, but line breaks .

3、 ... and 、 Double linked list

3.1 Linked list node class and linked list class

Similar to a single linked list :

class DLinkNode:
def __init__(self, data=None):
self.data = data
self.prior = None
self.next = None
class DLinkList:
def __init__(self):
self.dhead = DLinkNode()
self.dhead.prior = None
self.dhead.next = None

Like a single chain watch , The double linked list is also composed of head nodes head Uniquely identified .

3.2 Create a double linked list from an array

3.2.1 The first interpolation

def fromlist(self, a):
for i in range(len(a)):
s = DLinkList(a[i])
# First establish s A two-way relationship with its next node 
s.next = self.dhead.next
if self.dhead.next is not None:
self.dhead.next.prior = s
# Re establishment s A two-way relationship with its previous node 
self.dhead.next = s
s.prior = self.dhead

3.2.2 The tail interpolation

def fromlist(self, a):
t = self.dhead
for i in range(len(a)):
s = DLinkList(a[i])
# establish s Two way relationship with the end node of the linked list 
t.next = s
s.prior = t
# Move the pointer 
t = s
t.next = None

3.3 Some implementation of double linked list

3.3.1 Insert elements

Similar to a single linked list :

def insert(self, i, e):
assert i >= 0
p = self.geti(i - 1)
assert p is not None
s = DLinkNode(e)
s.next = p.next
if p.next is not None:
p.next.prior = s
p.next = s
s.prior = p

3.3.2 Remove elements

Similar to a single linked list :

def delete(self, i):
assert i >= 0
p = self.geti(i)
assert p is not None
p.prior.next = p.next
if p.next is not None:
p.next.prior = p.prior

Four 、 Circular linked list

4.1 Circular single chain table

The pointer attribute of the tail node of the circular single linked list is no longer None, It refers to the head node :

The characteristic of circular single linked list is that you can find other nodes from any node in the table . Compared with single chain table , No need to increase storage space , Only slightly modify the link method , It can make table processing more convenient 、 flexible .

The node type in the circular single linked list is the same as that in the acyclic single linked list , Still LinkNode.

class CLinkList:
def __init__(self):
self.head = LinkNode()
self.head.next = self.head # Because the linked list is empty at the beginning , So the head node refers to the head node 

The operations of inserting and deleting nodes in a circular single linked list are the same as those in an acyclic single linked list , So many basic algorithms of the two are similar , The main differences are as follows :

  • Initially, there are only header nodes head, In the construction method of circular single linked list, you need to pass head.next = head Statement to set an empty table ;
  • When the lookup operation is involved in the circular single linked list, you need Modify the conditions of footer judgment . For example, using p p p Ergodic time , The condition that the tail node satisfies is p.next == head instead of p.next == None.

4.2 Circular double linked list

Of the tail node of the circular double linked list next Pointer to head node , The first node prior The pointer points to the tail node :

Its characteristic is that the whole linked list forms two rings , From this, you can find other nodes from any node in the table , The most outstanding advantage is through the head node in O ( 1 ) \mathcal{O}(1) O(1) Find the tail node in time .

The node type in the circular double linked list is the same as that in the acyclic double linked list , Still DLinkNode.

class CDLinkList:
def __init__(self):
self.dhead = DLinkNode()
self.dhead.next = self.dhead
self.dhead.prior = self.dhead

5、 ... and 、 Comparison between sequential list and linked list

5.1 Space based considerations

For a storage structure , Define its storage density :
save Store The secret degree = The amount of storage occupied by the data itself in the node The storage occupied by the whole node Storage density =\frac{\text{ The amount of storage occupied by the data itself in the node }}{\text{ The storage occupied by the whole node }} save Store The secret degree = The storage occupied by the whole node The amount of storage occupied by the data itself in the node ​
In a general way , The higher the storage density , The higher the utilization of storage space .

obviously , The storage density of the sequence table is 1, The storage density of linked list is less than 1. Only from the storage density , The storage space utilization of sequential tables is higher .

Besides , The sequence table needs to allocate space in advance , If the space is too small, there will be overflow , If there is too much space, memory will be wasted . The storage space of the linked list is dynamically allocated , As long as there's enough memory , There will be no overflow .

therefore ,

  • When the length of the linear table changes little , When it is easy to determine in advance , A sequence table should be used .
  • When the length of the linear table changes greatly , It is difficult to estimate its storage size , A linked list should be used .

5.2 For the sake of time

From the perspective of search operation , The sequential table has the characteristics of random storage , Given the sequence number, the time to find the specified element is O ( 1 ) \mathcal{O}(1) O(1); And the linked list does not have the characteristics of random storage , Only sequential access , Given the sequence number, the time to find the specified element is O ( n ) \mathcal{O}(n) O(n).

From the perspective of insert and delete operations , Performing this operation in a sequential table usually requires moving the elements of half the table ; To perform this operation in the linked list, you only need to modify the pointer attribute of the relevant node , You don't have to move nodes .

therefore ,

  • If the main operation of a linear table is to find , A sequence table should be used ;
  • If the main operation of linear table is insert and delete , A linked list should be used ;

6、 ... and 、LeetCode actual combat

LeetCode The single linked list node in is defined as :

class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next

All the following code passed the test .

6.1 LeetCode#27—— Remove elements


This topic LeetCode Will automatically track nums, So just return an integer .

Method 1 : Double pointer

We can set two pointers :left and right. Where the right pointer points to the current element to be processed , The left pointer points to the next position to be assigned .

If the element pointed to by the right pointer is equal to val, Then the left pointer does not move , The right pointer moves one bit to the right . otherwise , Copy the element pointed by the right pointer to the position of the left pointer , Then move the left and right pointers to the right one bit at the same time .

class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
left = 0
for right in range(len(nums)):
if nums[right] != val:
nums[left] = nums[right]
left += 1
return left

Notice that the algorithm in the worst case , namely nums Does not include val, Both left and right pointers need to traverse the array once , That is, it has been traversed twice in total . Besides , The algorithm will repeatedly assign values to the elements to be preserved ( When left = right when ).

Complexity analysis

  • Time complexity : O ( n ) \mathcal{O}(n) O(n), among n n n Is the length of the sequence . We only need to traverse the sequence up to two times .
  • Spatial complexity : O ( 1 ) \mathcal{O}(1) O(1). We just need a constant space to hold a few variables .

Method 2 : Double pointer optimization

Consider initially placing the left and right pointers at both ends of the array .

When the left pointer points to val when , At this point, copy the element pointed to by the right pointer to the left pointer , At the same time, move the right pointer one bit to the left . If the copied element happens to be the same val, Then continue to perform the above operations until the left pointer points to something other than val.

When the left pointer points to something other than val when , Move the left pointer one bit to the right .

When the left and right pointers coincide , The left and right pointers traverse the entire array together .

class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
left, right = 0, len(nums) - 1
while left <= right:
if nums[left] == val:
nums[left] = nums[right]
right -= 1
else:
left += 1
return left

Complexity analysis

  • Time complexity : O ( n ) \mathcal{O}(n) O(n), among n n n Is the length of the sequence . We only need to traverse the sequence once more .
  • Spatial complexity : O ( 1 ) \mathcal{O}(1) O(1). We just need a constant space to hold a few variables .

6.2 LeetCode#26—— Delete duplicates in sort array


We can know from order , Duplicates must be connected . Besides , Because this question is not given val, So there may be many repetition elements .

say concretely , Set two left and right pointers , Initially, they are all at the left end of the array . When the right pointer points to the same element as the left pointer , The right pointer moves one bit to the right . If different , First move the left pointer to the right by one digit , Then copy the value pointed by the right pointer to the left pointer .

class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
left = 0
for right in range(len(nums)):
if nums[left] != nums[right]:
left += 1
nums[left] = nums[right]
return left + 1

6.3 LeetCode#80—— Delete duplicates in sort array II


We use the fast and slow pointer solution . Where the slow pointer indicates the length of the processed array , The fast pointer indicates the length of the array that has been checked .

Initially, set the speed pointer to the left end of the array , And the first two numbers of the array should be kept . Therefore, you should initially make the fast and slow pointers move synchronously to the index 2 2 2 Without any modification . Because the same element can appear twice at most , So it's more nums[slow - 2] and nums[fast], When they are the same , Only move the fast pointer to the right one digit ; When they are different , Copy the value pointed by the fast pointer to the left pointer , Then move the left and right pointers one bit to the right .

class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
slow = 0
for fast in range(len(nums)):
if slow < 2 or nums[slow - 2] != nums[fast]:
nums[slow] = nums[fast]
slow += 1
return slow

6.4 LeetCode#4—— Find the median of two ordered arrays



Pendulum rotten solution :

class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
nums = sorted(nums1 + nums2)
n = len(nums)
if n % 2 != 0:
return nums[n // 2]
else:
return (nums[n // 2 - 1] + nums[n // 2]) / 2

Because of the call sorted function , So time complexity is O ( ( m + n ) log ⁡ ( m + n ) ) \mathcal{O}((m+n)\log(m+n)) O((m+n)log(m+n)). So although the above code can run successfully , But it does not meet the requirements of the topic .

6.5 LeetCode#21—— Merge two ordered lists


Method 1 : iteration

First set a sentinel node sentinel, This makes it easier to return to the merged linked list at the end . We set three pointers l1l2 and prev,l1 and l2 To traverse separately list1 and list2. At the beginning prev Point to the sentinel node .

When l1 Less than l2 when , We will l1 The node pointed to is connected to prev after , And then prev and l1 Move back one bit . otherwise , We will l2 The node pointed to is connected to prev after , And then prev and l2 Move back one bit .

When the loop ends ,l1 and l2 At most one is not empty , Because the two input lists are ordered , So we just need to simply connect the non empty linked list to the merged linked list , And return to the merge list .

class Solution:
def mergeTwoLists(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
sentinel = ListNode(-1)
prev = sentinel
while l1 and l2:
if l1.val < l2.val:
prev.next = l1
l1 = l1.next
else:
prev.next = l2
l2 = l2.next
prev = prev.next
prev.next = l2 if l1 is None else l1
return sentinel.next

Time complexity : O ( m + n ) \mathcal{O}(m+n) O(m+n), Spatial complexity : O ( 1 ) \mathcal{O}(1) O(1).

Method 2 : recursive

class Solution:
def mergeTwoLists(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
# The boundary conditions 
if l1 is None:
return l2
if l2 is None:
return l1
# Recursive body 
if l1.val < l2.val:
l1.next = self.mergeTwoLists(l1.next, l2)
return l1
else:
l2.next = self.mergeTwoLists(l1, l2.next)
return l2

Time complexity : O ( m + n ) \mathcal{O}(m+n) O(m+n), Spatial complexity : O ( m + n ) \mathcal{O}(m+n) O(m+n).

Recursively call mergeTwoLists Function needs to consume stack space , The size of the stack space depends on the depth of the recursive call . End recursive call mergeTwoLists The function can call at most n + m n+m n+m Time , So the space complexity is zero O ( n + m ) \mathcal{O}(n+m) O(n+m).

6.6 LeetCode#83—— Delete duplicate elements from the sort list

class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
if not head:
return head
cur = head
while cur.next:
if cur.val == cur.next.val:
cur.next = cur.next.next
else:
cur = cur.next
return head

6.7 LeetCode#203—— Remove linked list elements


Because the head node may change , So we still use the sentinel node method . Besides , Set a pointer cur Used to traverse the entire list .

class Solution:
def removeElements(self, head: ListNode, val: int) -> ListNode:
if not head: return head
sentinel = ListNode(-1)
sentinel.next = head
cur = sentinel
while cur.next:
if cur.next.val == val:
cur.next = cur.next.next
else:
cur = cur.next
return sentinel.next

This problem can still be solved recursively .

class Solution:
def removeElements(self, head: ListNode, val: int) -> ListNode:
if not head: return head
head.next = self.removeElements(head.next, val)
# If head It needs to be deleted , Then return to head Next node of , Otherwise return to head In itself 
return head.next if head.val == val else head

6.8 LeetCode#19—— Delete the last of the linked list n Nodes

First of all, the easiest way to think of is to traverse twice . The first traverse calculates the total length of the linked list , The second traversal determines the node to be deleted . This method is too simple and crude, so I won't introduce it here .

For this question , We can set a speed pointer , Find a way to get the fast pointer to the end of the linked list , The slow pointer is just the penultimate n + 1 n+1 n+1 Nodes .

class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
sentinel = ListNode(-1, head)
slow, fast = sentinel, head
for _ in range(n):
fast = fast.next
while fast:
fast = fast.next
slow = slow.next
slow.next = slow.next.next
return sentinel.next

6.9 LeetCode#234—— Palindrome list

The roughest way is to store the values of the linked list in a list in turn nums in , And then through nums==nums[::-1] To judge whether the given list is a palindrome list .

Another idea is to press the first half of the linked list into the stack in turn , Then pop up the elements in the stack in turn and compare them with the latter half of the linked list . This method needs to consider the parity of the length of the linked list .

The space complexity of the above two methods is O ( n ) \mathcal{O}(n) O(n), Here is a O ( 1 ) \mathcal{O}(1) O(1) Solutions for —— Fast and slow pointer method .

The whole process is divided into the following steps :

  • Find the last node of the first half of the linked list . The speed pointer can be used , The slow pointer moves one bit at a time , The fast pointer moves two digits at a time .
  • Reverse the second half of linked list .
  • Set the left and right pointers , Located at the beginning of the first half and the beginning of the second half , Then move to the right step by step to judge whether the palindrome .
  • Return results .
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
if not head: return True
first_half_end = self.get_middle_position(head)
second_half_start = self.reverse_list(first_half_end.next)
flag = True
left, right = head, second_half_start
while flag and right:
if left.val != right.val:
flag = False
left = left.next
right = right.next
return flag
def get_middle_position(self, head):
slow, fast = head, head
while fast.next and fast.next.next:
slow = slow.next
fast = fast.next.next
return slow
def reverse_list(self, head):
prev, cur = None, head
while cur:
next_node = cur.next
cur.next = prev
prev = cur
cur = next_node
return prev

Strictly speaking , We should also restore the linked list after judgment .

6.10 LeetCode#61—— Rotate the list


You can first form a circular linked list , Then cut the designated position .

class Solution:
def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
if not head: return head
# Form a circular linked list and calculate the length of the linked list 
p = head
length = 1
while p.next:
p = p.next
length += 1
p.next = head
# break link 
pos = length - k % length
p = head
k = 1
while k < pos:
p = p.next
k += 1
next_node = p.next
p.next = None
return next_node

7、 ... and 、 appendix

7.1 Single linked list complete code

class LinkNode:
def __init__(self, data=None):
self.data = data
self.next = None
class LinkList:
def __init__(self):
self.head = LinkNode()
self.head.next = None
def fromlist(self, a):
t = self.head
for i in range(len(a)):
s = LinkNode(a[i])
t.next = s
t = s
t.next = None
def geti(self, i):
p = self.head
j = -1
while j < i and p is not None:
p = p.next
j += 1
return p
def add(self, e):
p = self.head
s = LinkNode(e)
while p.next is not None:
p = p.next
p.next = s
def insert(self, i, e):
assert i >= 0
p = self.geti(i - 1)
assert p is not None
s = LinkNode(e)
s.next = p.next
p.next = s
def delete(self, i):
assert i >= 0
p = self.geti(i - 1)
assert p is not None and p.next is not None
p.next = p.next.next
def __getitem__(self, i):
assert i >= 0
p = self.geti(i)
assert p is not None
return p.data
def __setitem__(self, i, x):
assert i >= 0
p = self.geti(i)
assert p is not None
p.data = x
def getno(self, e):
p = self.head.next
k = 0
while p is not None and p.data != e:
p = p.next
k += 1
return -1 if p is None else k
def getsize(self):
p = self.head.next
j = 1
while p.next is not None:
p = p.next
j += 1
return j
def display(self):
p = self.head.next
while p.next is not None:
print(p.data, end=' ')
p = p.next
print(p.data)

7.2 Double linked list complete code

class DLinkNode:
def __init__(self, data=None):
self.data = data
self.prior = None
self.next = None
class DLinkList:
def __init__(self):
self.dhead = DLinkNode()
self.dhead.prior = None
self.dhead.next = None
def fromlist(self, a):
t = self.dhead
for i in range(len(a)):
s = DLinkList(a[i])
# establish s Two way relationship with the end node of the linked list 
t.next = s
s.prior = t
# Move the pointer 
t = s
t.next = None
def geti(self, i):
p = self.dhead
j = -1
while j < i and p is not None:
p = p.next
j += 1
return p
def insert(self, i, e):
assert i >= 0
p = self.geti(i - 1)
assert p is not None
s = DLinkNode(e)
s.next = p.next
if p.next is not None:
p.next.prior = s
p.next = s
s.prior = p
def delete(self, i):
assert i >= 0
p = self.geti(i)
assert p is not None
p.prior.next = p.next
if p.next is not None:
p.next.prior = p.prior

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved