- vừa được xem lúc

Singly Linked List trong Python

0 0 5

Người đăng: thavrith

Theo Viblo Asia

Bài viết nằm trong series Data Structures và Algorithms trong Python

Singly Linked List

Giới thiệu

Mỗi Singly Linked List bao gồm nhiều nodes, và mỗi node chứa hai thành phần chính:

  1. Data
  • Component data cho phép mỗi node trong singly linked list lưu trữ một phần tử dữ liệu. Phần tử này có thể là string, character, number, hoặc bất kỳ kiểu dữ liệu nào khác.
  1. Next (con trỏ)
  • Component thứ hai, là một con trỏ (pointer) trỏ từ node hiện tại đến node tiếp theo trong danh sách liên kết. Component next này giúp kết nối các node lại với nhau, tạo thành chuỗi liên kết.

Head là điểm bắt đầu của linked list. Head không phải là một node mà là một con trỏ trỏ đến node đầu tiên trong danh sách. Khi cần duyệt qua linked list hoặc truy cập một phần tử, chúng ta sẽ bắt đầu từ head và di chuyển theo hướng của các node tiếp theo bằng cách sử dụng con trỏ next.

Component cuối cùng của singly linked list là null. Trong Python là None, biểu thị rằng đây là node cuối cùng và không có node nào tiếp theo nữa.

class Node: def __init__(self, data): self.data = data # Dữ liệu mà node lưu trữ self.next = None # Con trỏ trỏ đến node tiếp theo (ban đầu là None) class SinglyLinkedList: def __init__(self): self.head = None # Khởi tạo danh sách với head là None (danh sách trống)

display()

Chúng ta sẽ bắt đầu từ con trỏ head và in ra dữ liệu của từng node, sau đó di chuyển đến node tiếp theo. Ta sẽ tiếp tục kiểm tra node tiếp theo để đảm bảo rằng nó không phải là None. Nếu không phải, ta sẽ tiếp tục di chuyển đến node kế tiếp. Quy trình này sẽ lặp lại cho đến khi chạm tới node cuối cùng, nơi con trỏ nextNone.

def display(self): current_node = self.head while current_node: # Duyệt qua danh sách cho đến khi gặp None print(current_node.data, end=" -> ") current_node = current_node.next print("None")

Insertion

Append

Phương thức append sẽ chèn một phần tử vào cuối linked list.

Trường hợp Linked List rỗng

Khi triển khai phương thức append cho linked list, chúng ta cần xử lý trường hợp đặc biệt nếu linked list rỗng. Trong trường hợp list rỗng (tức là head bằng None), node mới sẽ trở thành head của danh sách. Dưới đây là cách triển khai phương thức append bao gồm xử lý cho trường hợp list rỗng:


# Phương thức append: Chèn một phần tử mới vào cuối danh sách
def append(self, data): new_node = Node(data) # Nếu danh sách rỗng, node mới sẽ là head if not self.head: self.head = new_node return

Trường hợp Linked List không rỗng

Trong trường hợp linked list không rỗng, chúng ta cần duyệt qua linked list để tìm node cuối cùng và thêm node mới vào cuối danh sách.


# Phương thức append: Chèn một phần tử mới vào cuối danh sách
def append(self, data): new_node = Node(data) # Nếu danh sách rỗng, node mới sẽ là head if not self.head: self.head = new_node return # Nếu danh sách không rỗng, tìm node cuối và gắn node mới vào cuối last_node = self.head while last_node.next: last_node = last_node.next last_node.next = new_node

Sử dụng append

# Sử dụng danh sách liên kết
sll = SinglyLinkedList() # Thêm các phần tử vào danh sách
sll.append(1)
sll.append(2)
sll.append(3) # Hiển thị danh sách
sll.display() # Output: 1 -> 2 -> 3 -> None

Prepend

Phương thức prepend sẽ chèn một phần tử vào đầu linked list. Khi thêm một node mới vào đầu danh sách, chúng ta chỉ cần thay đổi con trỏ head để trỏ đến node mới, và con trỏ của node mới sẽ trỏ đến node cũ mà head trỏ đến trước đó.

def prepend(self, data): new_node = Node(data) # Tạo node mới new_node.next = self.head # Con trỏ của node mới trỏ đến node đầu hiện tại self.head = new_node # Cập nhật head để trỏ đến node mới

Sử dụng

# Sử dụng danh sách liên kết
sll = SinglyLinkedList() # Thêm các phần tử vào danh sách
sll.prepend("C") # Danh sách: C
sll.prepend("B") # Danh sách: B -> C
sll.prepend("A") # Danh sách: A -> B -> C # Thêm phần tử D vào đầu danh sách
sll.prepend("D") # Danh sách: D -> A -> B -> C # Hiển thị danh sách
sll.display() # Output: D -> A -> B -> C -> None

Insert After Node

Phương thức insert_after_node sẽ chèn một node mới sau một node cụ thể đã có trong linked list. Để triển khai phương thức này, ta cần tìm node đích và sau đó thêm node mới ngay sau nó. Điều này yêu cầu cập nhật các con trỏ để đảm bảo rằng danh sách liên kết vẫn duy trì cấu trúc chính xác.

def insert_after_node(self, prev_node_data, data): current_node = self.head while current_node: # Duyệt qua danh sách if current_node.data == prev_node_data: # Tìm node đích new_node = Node(data) # Tạo node mới new_node.next = current_node.next # Con trỏ của node mới trỏ đến node tiếp theo của node đích current_node.next = new_node # Cập nhật con trỏ của node đích trỏ đến node mới return current_node = current_node.next print(f"Node với giá trị {prev_node_data} không tồn tại trong danh sách liên kết.")

Sử dụng:

# Sử dụng danh sách liên kết
sll = SinglyLinkedList() # Thêm các phần tử vào danh sách
sll.append("A")
sll.append("B")
sll.append("C") # Chèn phần tử sau node "B"
sll.insert_after_node("B", "D") # Hiển thị danh sách
sll.display() # Output: A -> B -> D -> C -> None # Chèn phần tử sau node "F"
sll.insert_after_node("F", "D") # Output: Node với giá trị F không tồn tại trong danh sách liên kết.

Insert a node at a specific position in a linked list

Để chèn một phần tử vào vị trí cụ thể trong singly linked list, ta cần xử lý hai trường hợp chính:

  • Chèn tại vị trí 0: ta chỉ cần cập nhật con trỏ next của node mới để trỏ đến head hiện tại, sau đó cập nhật head trỏ đến node mới.
  • Chèn tại vị trí bất kỳ khác: Nếu position lớn hơn 0, ta sẽ duyệt qua danh sách để tìm node trước (prev_node) vị trí cần chèn. Sau đó, ta chèn node mới giữa node trướcnode tại vị trí đó.
def insert_at_position(self, position, data): new_node = Node(data) # Trường hợp vị trí là 0 (chèn vào đầu danh sách) if position == 0: new_node.next = self.head self.head = new_node return # Trường hợp chèn vào vị trí bất kỳ khác current_node = self.head count = 0 prev_node = None # Duyệt qua danh sách để tìm vị trí cần chèn while current_node and count < position: prev_node = current_node current_node = current_node.next count += 1 # Nếu vị trí vượt quá kích thước của danh sách if count != position: print(f"Vị trí {position} vượt quá kích thước của danh sách.") return # Chèn node mới vào vị trí đã tìm thấy new_node.next = current_node prev_node.next = new_node

Sử dụng

# Sử dụng danh sách liên kết
llist = SinglyLinkedList() # Thêm các phần tử vào danh sách
llist.append("A")
llist.append("B")
llist.append("C") # Hiển thị danh sách ban đầu
print("Danh sách ban đầu:")
llist.display() # Chèn node tại vị trí 0 (đầu danh sách)
llist.insert_at_position(0, "D") # Hiển thị danh sách sau khi chèn tại vị trí 0
print("\nDanh sách sau khi chèn tại vị trí 0:")
llist.display() # Chèn node tại vị trí 2
llist.insert_at_position(2, "E") # Hiển thị danh sách sau khi chèn tại vị trí 2
print("\nDanh sách sau khi chèn tại vị trí 2:")
llist.display()

Output

Danh sách ban đầu: A -> B -> C -> None Danh sách sau khi chèn tại vị trí 0:
D -> A -> B -> C -> None Danh sách sau khi chèn tại vị trí 2:
D -> A -> E -> B -> C -> None 

Deletion

Xóa bởi giá trị

Chúng ta có 2 trường hợp:

  • Node cần xóa là node đầu tiên (head).
  • Node cần xóa không phải là node đầu tiên (head).

Node cần xóa là node đầu tiên

Nếu node cần xóa là head, ta chỉ cần cập nhật con trỏ head để trỏ đến node tiếp theo của head. Điều này sẽ xóa đi liên kết của head hiện tại, và danh sách liên kết vẫn sẽ được duy trì.

def delete_node(self, key): # Trường hợp node cần xóa là head if self.head and self.head.data == key: self.head = self.head.next return

Node cần xóa không phải là node đầu tiên

Nếu node cần xóa không phải là head, ta sẽ duyệt qua danh sách để tìm node trước node cần xóa. Sau khi tìm thấy, ta sẽ cập nhật con trỏ next của node trước này để trỏ đến node tiếp theo của node cần xóa, và điều này sẽ xóa bỏ node cần xóa ra khỏi danh sách.

def delete_node(self, key): current_node = self.head # Trường hợp node cần xóa là head if current_node and current_node.data == key: self.head = current_node.next current_node = None return # Trường hợp node cần xóa không phải là head prev_node = None while current_node and current_node.data != key: prev_node = current_node current_node = current_node.next # Nếu node cần xóa không tồn tại trong danh sách if current_node is None: print(f"Node với giá trị {key} không tồn tại trong danh sách liên kết.") return # Cập nhật con trỏ của node trước trỏ đến node tiếp theo của node bị xóa prev_node.next = current_node.next current_node = None

Sử dụng

 # Sử dụng danh sách liên kết llist = SinglyLinkedList() # Thêm các phần tử vào danh sách llist.append("A")
llist.append("B")
llist.append("C")
llist.append("D") # Hiển thị danh sách ban đầu print("Danh sách ban đầu:")
llist.display() # Xóa node "B" (không phải head) llist.delete_node("B") # Hiển thị danh sách sau khi xóa print("\nDanh sách sau khi xóa B:")
llist.display() # Xóa node "A" (là head) llist.delete_node("A") # Hiển thị danh sách sau khi xóa print("\nDanh sách sau khi xóa A (head):")
llist.display() 

Output

Danh sách ban đầu:
A -> B -> C -> D -> None Danh sách sau khi xóa B:
A -> C -> D -> None Danh sách sau khi xóa A (head):
C -> D -> None

Xóa bởi vị trí

Để xóa một node theo vị trí cụ thể trong singly linked list (danh sách liên kết đơn), ta sẽ xử lý hai trường hợp:

  • Node cần xóa ở vị trí 0 (node đầu tiên - head): Đây là trường hợp đặc biệt khi node cần xóa là head, ta chỉ cần cập nhật con trỏ head để trỏ đến node tiếp theo.

  • Node cần xóa không ở vị trí 0: Trong trường hợp này, ta cần duyệt qua danh sách đến vị trí cần xóa, tìm node trước vị trí đó và cập nhật con trỏ của node trước để bỏ qua node cần xóa.

Xóa node ở vị trí 0

def delete_at_position(self, position): if self.head is None: print("Danh sách trống.") return current_node = self.head # Trường hợp node cần xóa ở vị trí 0 (node đầu tiên) if position == 0: self.head = current_node.next # Cập nhật head để trỏ đến node tiếp theo current_node = None return

Xóa node ở các vị trí khác

def delete_at_position(self, position): if self.head is None: print("Danh sách trống.") return current_node = self.head # Trường hợp node cần xóa ở vị trí 0 (node đầu tiên) if position == 0: self.head = current_node.next # Cập nhật head để trỏ đến node tiếp theo current_node = None return # Trường hợp node cần xóa không phải ở vị trí 0 prev_node = None count = 0 # Duyệt qua danh sách đến vị trí cần xóa while current_node and count != position: prev_node = current_node current_node = current_node.next count += 1 # Nếu vị trí không tồn tại trong danh sách if current_node is None: print(f"Vị trí {position} vượt quá kích thước của danh sách.") return # Cập nhật con trỏ của node trước trỏ đến node tiếp theo của node bị xóa prev_node.next = current_node.next current_node = None

Sử dụng:


# Sử dụng danh sách liên kết
llist = SinglyLinkedList() # Thêm các phần tử vào danh sách llist.append("A")
llist.append("B")
llist.append("C")
llist.append("D")
llist.append("E") # Hiển thị danh sách ban đầu print("Danh sách ban đầu:")
llist.display() # Xóa node tại vị trí 0 (head) llist.delete_at_position(0) # Hiển thị danh sách sau khi xóa node tại vị trí 0 print("\nDanh sách sau khi xóa vị trí 0 (head):")
llist.display() # Xóa node tại vị trí 2 llist.delete_at_position(2) # Hiển thị danh sách sau khi xóa node tại vị trí 2 print("\nDanh sách sau khi xóa vị trí 2:")
llist.display() 

Output

Danh sách ban đầu: A -> B -> C -> D -> E -> None Danh sách sau khi xóa vị trí 0 (head):
B -> C -> D -> E -> None Danh sách sau khi xóa vị trí 2:
B -> C -> E -> None 

File code singly-linked-list cho tới lúc này

Length

Iterative

def get_length_iterative(self): count = 0 current_node = self.head while current_node: # Duyệt qua danh sách cho đến khi gặp None count += 1 current_node = current_node.next return count

Recursive

def get_length_recursive(self, node): # Nếu node là None, tức là danh sách rỗng if not node: return 0 # Tính độ dài đệ quy cho các node tiếp theo return 1 + self.get_length_recursive(node.next)

Node Swap

Trường hợp cần xử lý khi swap 2 nodes:

  • Node 1 và Node 2 không phải là head.
  • Một trong hai node là head.
  • Hai node cần hoán đổi là giống nhau (không cần thực hiện gì).

Các bước để thực hiện swap 2 nodes:

  • Tìm vị trí của hai node cần hoán đổi.
  • Nếu một trong hai node là head, cập nhật con trỏ head để trỏ đến node kia.
  • Cập nhật các con trỏ của các node trước hai node cần hoán đổi để giữ liên kết giữa các node trong danh sách.
 def swap_nodes(self, key1, key2): # Nếu hai node giống nhau, không cần hoán đổi if key1 == key2: return # Tìm vị trí của key1 prev_node1 = None current_node1 = self.head while current_node1 and current_node1.data != key1: prev_node1 = current_node1 current_node1 = current_node1.next # Tìm vị trí của key2 prev_node2 = None current_node2 = self.head while current_node2 and current_node2.data != key2: prev_node2 = current_node2 current_node2 = current_node2.next # Nếu không tìm thấy một trong hai node (None), dừng lại if not current_node1 or not current_node2: print("Một hoặc cả hai node không tồn tại.") return # Nếu key1 không phải là head, cập nhật con trỏ của prev_node1 if prev_node1: prev_node1.next = current_node2 else: # Nếu key1 là head self.head = current_node2 # Nếu key2 không phải là head, cập nhật con trỏ của prev_node2 if prev_node2: prev_node2.next = current_node1 else: # Nếu key2 là head self.head = current_node1 # Hoán đổi con trỏ next của hai node current_node1.next, current_node2.next = current_node2.next, current_node1.next

Sử dụng:

llist = SinglyLinkedList() print("------------------------------") llist.append("A")
llist.append("B")
llist.append("C")
llist.append("D")
# Hiển thị danh sách ban đầu
print("Danh sách ban đầu:")
llist.display() # Hoán đổi hai node
llist.swap_nodes("A", "D") # Hiển thị danh sách sau khi hoán đổi
print("\nDanh sách sau khi hoán đổi A và D:")
llist.display()

Output

------------------------------
Danh sách ban đầu:
A -> B -> C -> D -> None Danh sách sau khi hoán đổi A và D:
D -> B -> C -> A -> None

Giải thích

  1. Tìm hai node cần hoán đổi:
  • Ta duyệt qua danh sách liên kết để tìm prev_nodecurrent_node cho cả hai node cần hoán đổi (key1key2).
  1. Cập nhật liên kết:
  • Nếu một trong hai node là head, ta cập nhật head trỏ đến node kia.
  • Sau đó, ta cập nhật con trỏ của node trước để nó trỏ đến node còn lại.

Ví dụ key1"A": head, key2"D" thì

  • self.head sẽ trỏ đến current_node2 ("D")
  • prev_node2.next ("C") sẽ trỏ đến current_node1 ("A")
  1. Hoán đổi các con trỏ next:
  • Cuối cùng, ta hoán đổi con trỏ next của hai node hiện tại (current_node1.nextcurrent_node2.next) để hoàn tất việc hoán đổi các node trong danh sách liên kết. Sau A (current_node1.next) sẽ là None (current_node2.next) và sau D (current_node2.next) sẽ là B (current_node1.next)
  1. Trường hợp không tìm thấy node:
  • Nếu không tìm thấy một trong hai node, chương trình sẽ thông báo và dừng lại.

Minh họa

File code singly-linked-list cho tới lúc này

Reverse

Iterative

def reverse_iterative(self): prev = None current = self.head while current: next_node = current.next # Lưu trữ node tiếp theo current.next = prev # Đảo ngược liên kết prev = current # Di chuyển prev lên current = next_node # Di chuyển current lên node tiếp theo self.head = prev # Cập nhật head để trỏ đến node cuối cùng (bây giờ là node đầu tiên)
  • prev bắt đầu là None vì node cuối cùng của danh sách liên kết đảo ngược sẽ trỏ đến None.
  • currenthead, ta se duyệt qua từng node trong danh sách liên kết. Tại mỗi bước:
    • Ta lưu trữ node tiếp theo của current trong next_node.
    • Đảo ngược liên kết của node hiện tại (current.next) để trỏ về node trước (prev).
    • Cập nhật prev thành currentcurrent thành next_node để tiếp tục duyệt danh sách.
  • Cuối cùng, head được cập nhật để trỏ đến node cuối cùng, là node đầu tiên trong danh sách đảo ngược.

Merge Two Sorted Linked Lists

Ý tưởng cơ bản là so sánh các phần tử từ hai danh sách liên kết và xây dựng một danh sách mới bằng cách liên kết các node theo thứ tự.

 def merge_sorted_lists(self, other_list): head1 = self.head # con trỏ tới đầu danh sách 1 head2 = other_list.head # con trỏ tới đầu danh sách 2 tail = None # theo dõi phần cuối của merged list # Kiểm tra nếu danh sách đầu tiên rỗng if not head1: return head2 # Kiểm tra nếu danh sách thứ hai rỗng if not head2: return head1 # Bắt đầu so sánh giá trị của hai danh sách if head1 and head2: if head1.data <= head2.data: tail = head1 head1 = tail.next else: tail = head2 head2 = tail.next new_head = tail # new_head là con trỏ tới đầu merged list # Duyệt qua hai danh sách và tiếp tục so sánh các phần tử while head1 and head2: if head1.data <= head2.data: tail.next = head1 # Kết nối node nhỏ hơn từ head1 tail = head1 head1 = tail.next else: tail.next = head2 # Kết nối node nhỏ hơn từ head2 tail = head2 head2 = tail.next # Nếu head1 hết node, nối phần còn lại của head2 if not head1: tail.next = head2 # Nếu head2 hết node, nối phần còn lại của head1 if not head2: tail.next = head1 self.head = new_head # Cập nhật lại head của merged list return self.head
  1. Kiểm tra danh sách rỗng:
  • Nếu một trong hai danh sách rỗng, trả về danh sách còn lại.
  1. Xác định node đầu tiên của merged list
  • So sánh giá trị của node đầu tiên từ cả hai danh sách, chọn node có giá trị nhỏ hơn làm new_head (node đầu tiên của merged list).
  1. Merge hai danh sách:
  • Duyệt qua hai danh sách bằng cách so sánh từng node. Node nào nhỏ hơn sẽ được thêm vào merged list trước.
  1. Nối phần còn lại:
  • Khi một trong hai danh sách hết node, nối tất cả các node còn lại của danh sách kia vào.
  1. Cập nhật self.head:
  • Cập nhật self.head để trỏ đến node đầu tiên của merged list và trả về nếu có cần sử dụng cho mục đích khác.

Sử dụng

# Sử dụng danh sách liên kết
llist1 = SinglyLinkedList()
llist2 = SinglyLinkedList() # Thêm các phần tử vào danh sách liên kết 1 (đã sắp xếp)
llist1.append(1)
llist1.append(3)
llist1.append(5) # Thêm các phần tử vào danh sách liên kết 2 (đã sắp xếp)
llist2.append(2)
llist2.append(4)
llist2.append(6) print("Danh sách liên kết 1:")
llist1.display() print("Danh sách liên kết 2:")
llist2.display() # Gộp hai danh sách liên kết đã sắp xếp
llist1.merge_sorted_lists(llist2) print("\nDanh sách liên kết sau khi gộp:")
llist1.display()

Output

Danh sách liên kết 1: 1 -> 3 -> 5 -> None
Danh sách liên kết 2:
2 -> 4 -> 6 -> None Danh sách liên kết sau khi gộp:
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> None

Remove Duplicates

  • Duyệt qua danh sách liên kết, sử dụng set để lưu các giá trị đã gặp.
  • Mỗi khi gặp một giá trị mới, thêm nó vào set.
  • Nếu gặp một giá trị đã tồn tại trong set, ta xóa node đó khỏi danh sách.
 # Xóa các phần tử trùng lặp trong danh sách def remove_duplicates(self): if not self.head: return current = self.head prev = None seen_data = set() # Tập hợp để lưu các giá trị đã gặp while current: if current.data in seen_data: # Nếu giá trị đã gặp prev.next = current.next # Bỏ qua node hiện tại (current) else: seen_data.add(current.data) # Thêm giá trị vào tập hợp prev = current # Cập nhật con trỏ prev current = current.next # Di chuyển đến node tiếp theo
  1. Duyệt qua danh sách:
  • Sử dụng con trỏ current để duyệt qua từng node của danh sách.
  • Con trỏ prev để theo dõi node trước đó, giúp ta cập nhật liên kết khi xóa một node trùng lặp.
  1. Kiểm tra giá trị trùng lặp:
  • Sử dụng set (seen_data) để lưu trữ các giá trị đã gặp.
  • Mỗi khi gặp một giá trị mới, ta thêm nó vào tập hợp.
  • Nếu giá trị đã tồn tại trong tập hợp, ta xóa node hiện tại bằng cách thay đổi con trỏ next của prev.
  1. Cập nhật liên kết:
  • Nếu phát hiện trùng lặp, ta bỏ qua node đó bằng cách thay đổi liên kết giữa prevcurrent.next.

Sử dụng

# Sử dụng danh sách liên kết
llist = SinglyLinkedList() # Thêm các phần tử vào danh sách
llist.append(1)
llist.append(2)
llist.append(2)
llist.append(3)
llist.append(4)
llist.append(4)
llist.append(5) print("Danh sách ban đầu:")
llist.display() # Xóa các phần tử trùng lặp
llist.remove_duplicates() print("Danh sách sau khi xóa các phần tử trùng lặp:")
llist.display()

Output

Danh sách ban đầu:
1 -> 2 -> 2 -> 3 -> 4 -> 4 -> 5 -> None
Danh sách sau khi xóa các phần tử trùng lặp:
1 -> 2 -> 3 -> 4 -> 5 -> None

Nth-to-Last Node

  • Tính độ dài của danh sách
  • Xác định vị trí của node thứ N từ cuối target_index = length - N
  • Duyệt qua danh sách từ đầu đến vị trí target_index.
  • Trả về node tại vị trí đó nếu tìm thấy, nếu N không hợp lệ (lớn hơn độ dài của danh sách hoặc N <= 0), trả về None.
 def nth_to_last_node(self, N): length = self.get_length_iterative() # Tính độ dài của danh sách if N > length or N <= 0: # Kiểm tra xem N có hợp lệ không return None target_index = length - N # Vị trí tương đương từ đầu danh sách current = self.head count = 0 while current: if count == target_index: return current # Trả về node thứ N từ cuối count += 1 current = current.next return None

Count Occurrences

Hàm count_occurrences sẽ duyệt qua từng node của danh sách, kiểm tra giá trị của từng node và đếm số lần giá trị mà ta muốn kiểm tra xuất hiện trong danh sách.

# Phương thức đếm số lần xuất hiện của một giá trị def count_occurrences(self, value): count = 0 current = self.head while current: if current.data == value: count += 1 current = current.next return count

Is Palindrome

Để kiểm tra xem một Singly Linked List có phải là palindrome hay không, chúng ta có thể sử dụng nhiều phương pháp khác nhau.

Sử dụng List

 def is_palindrome(self): values = [] current = self.head # Lưu các giá trị của danh sách liên kết vào một list while current: values.append(current.data) current = current.next # Kiểm tra xem list có phải là palindrome không return values == values[::-1]

Kết bài

Singly Linked List là một trong những cấu trúc dữ liệu cơ bản và quan trọng trong lập trình. Nó cung cấp một cách hiệu quả để lưu trữ và quản lý dữ liệu động, với các thao tác CRUD mà không cần cấp phát lại bộ nhớ như mảng. Tuy nhiên, điểm hạn chế của Singly Linked List là khó truy cập ngẫu nhiên đến các phần tử so với cấu trúc dữ liệu như mảng, do phải duyệt tuần tự qua từng node.

Việc nắm vững các thao tác trong Singly Linked List sẽ giúp ta áp dụng chúng một cách hiệu quả trong các bài toán lập trình. Hơn nữa, hiểu rõ các thuật toán liên quan đến danh sách liên kết đơn như reverse, kiểm tra palindrome, hay merge sorted list sẽ nâng cao kỹ năng xử lý dữ liệu của ta trong những tình huống thực tế.

Dù là một cấu trúc dữ liệu đơn giản, Singly Linked List vẫn là nền tảng quan trọng để hiểu sâu hơn về các cấu trúc dữ liệu phức tạp hơn, và sẽ trở thành công cụ mạnh mẽ khi bạn giải quyết những bài toán cần sự linh hoạt trong quản lý dữ liệu.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Đệ quy và ngăn xếp triển khai như thế nào?

Giới thiệu. . Là lập trình viên chắc hẳn chúng ta đã nghe về đệ quy, vậy đệ quy là gì. .

0 0 33

- vừa được xem lúc

Singly Linked List

Tổng quan. Hai bài trước chúng ta đã tìm hiểu về Array và Hash Table.

0 0 164

- vừa được xem lúc

Doubly Linked List

Tổng quan. Tiếp theo chúng ta sẽ tiếp tục tìm hiểu về một loại Linked List khác, được gọi là Doubly Linked List.

0 0 38

- vừa được xem lúc

Bài 14: Cấp phát bộ nhớ động và Danh sách liên kết (Phần 2) - Danh sách liên kết (Linked List)

Đây là bài viết số 2 thuộc bài học Cấp phát bộ nhớ động và Danh sách liên kết của chuyên đề lập trình C++ cơ bản. Để nắm vững bài viết này, trước tiên các bạn hãy tìm đọc lại các bài viết trước đây gồ

0 0 15

- vừa được xem lúc

Doubly Linked List trong Python

Danh sách liên kết đôi (Doubly Linked List) giống với danh sách liên kết đơn (Singly Linked List), nhưng có thêm sự khác biệt là con trỏ prev trong mỗi node. .

0 0 5

- vừa được xem lúc

Doubly Linked List trong Python

Danh sách liên kết đôi (Doubly Linked List) giống với danh sách liên kết đơn (Singly Linked List), nhưng có thêm sự khác biệt là con trỏ prev trong mỗi node. .

0 0 5