杰瑞科技汇

Python链表如何实现与操作?

Of course! Here is a comprehensive guide to implementing and using a Linked List in Python.

What is a Linked List?

A Linked List is a linear data structure, but unlike an array, its elements are not stored at contiguous memory locations. Instead, each element is a separate object called a node.

Each node contains two pieces of information:

  1. Data: The actual value the node holds.
  2. Next: A pointer (or reference) to the next node in the sequence. The last node's next pointer points to None.

The entire list is accessed through a single pointer, usually called the head, which points to the first node.

Analogy: Think of a treasure hunt. Each clue (node) tells you where to find the next clue (the next pointer). The head is the first clue you are given.


The Node Class

First, we need to create the building block of a linked list: the Node.

class Node:
    """A node in a singly linked list."""
    def __init__(self, data):
        self.data = data  # The data stored in the node
        self.next = None  # The pointer to the next node, initially None
    def __repr__(self):
        # A helpful representation for printing the node
        return f"Node({self.data})"

The LinkedList Class

Now, let's create the LinkedList class itself. This class will manage the nodes and provide methods to interact with the list.

Basic Structure and Initialization

class LinkedList:
    """A singly linked list."""
    def __init__(self):
        self.head = None  # The head of the list, initially empty
    def __repr__(self):
        """Returns a string representation of the list."""
        nodes = []
        current_node = self.head
        while current_node:
            nodes.append(str(current_node.data))
            current_node = current_node.next
        return " -> ".join(nodes) + " -> None"
    def is_empty(self):
        """Returns True if the list is empty, False otherwise."""
        return self.head is None

Core Operations

Here are the fundamental methods for manipulating a linked list.

a. Append (Add to the End)

This is the most common operation. We traverse the list to find the last node and then link the new node to it.

    def append(self, data):
        """Adds a new node with the given data to the end of the list."""
        new_node = Node(data)
        # If the list is empty, the new node becomes the head
        if self.is_empty():
            self.head = new_node
            return
        # Otherwise, traverse to the end of the list
        last_node = self.head
        while last_node.next:
            last_node = last_node.next
        # Link the last node to the new node
        last_node.next = new_node

b. Prepend (Add to the Beginning)

This is very efficient as it doesn't require traversal. We just update the head.

    def prepend(self, data):
        """Adds a new node with the given data to the beginning of the list."""
        new_node = Node(data)
        new_node.next = self.head  # The new node now points to the old head
        self.head = new_node       # The new node becomes the new head

c. Delete (by Value)

This involves finding the node with the given data and removing it from the chain. We need to keep track of the previous node to "stitch" the list back together.

    def delete(self, data):
        """
        Deletes the first occurrence of a node with the given data.
        """
        # Case 1: The list is empty
        if self.is_empty():
            print("List is empty, cannot delete.")
            return
        # Case 2: The node to delete is the head
        if self.head.data == data:
            self.head = self.head.next
            return
        # Case 3: The node is somewhere else in the list
        # We need to find the node *before* the one to delete
        current_node = self.head
        while current_node.next and current_node.next.data != data:
            current_node = current_node.next
        # If we reached the end, the data was not found
        if current_node.next is None:
            print(f"Data '{data}' not found in the list.")
        else:
            # Unlink the node by skipping over it
            current_node.next = current_node.next.next

Putting It All Together: A Full Example

Here is the complete code for the Node and LinkedList classes with all the methods discussed.

class Node:
    """A node in a singly linked list."""
    def __init__(self, data):
        self.data = data
        self.next = None
    def __repr__(self):
        return f"Node({self.data})"
class LinkedList:
    """A singly linked list."""
    def __init__(self):
        self.head = None
    def __repr__(self):
        """Returns a string representation of the list."""
        nodes = []
        current_node = self.head
        while current_node:
            nodes.append(str(current_node.data))
            current_node = current_node.next
        return " -> ".join(nodes) + " -> None"
    def is_empty(self):
        """Returns True if the list is empty, False otherwise."""
        return self.head is None
    def append(self, data):
        """Adds a new node with the given data to the end of the list."""
        new_node = Node(data)
        if self.is_empty():
            self.head = new_node
            return
        last_node = self.head
        while last_node.next:
            last_node = last_node.next
        last_node.next = new_node
    def prepend(self, data):
        """Adds a new node with the given data to the beginning of the list."""
        new_node = Node(data)
        new_node.next = self.head
        self.head = new_node
    def delete(self, data):
        """Deletes the first occurrence of a node with the given data."""
        if self.is_empty():
            print("List is empty, cannot delete.")
            return
        if self.head.data == data:
            self.head = self.head.next
            return
        current_node = self.head
        while current_node.next and current_node.next.data != data:
            current_node = current_node.next
        if current_node.next is None:
            print(f"Data '{data}' not found in the list.")
        else:
            current_node.next = current_node.next.next
    def find(self, data):
        """Searches for a node with the given data and returns it, or None."""
        current_node = self.head
        while current_node:
            if current_node.data == data:
                return current_node
            current_node = current_node.next
        return None
# --- DEMONSTRATION ---
# 1. Create a new linked list
ll = LinkedList()
print(f"Initial list: {ll}")
print(f"Is list empty? {ll.is_empty()}")
print("-" * 20)
# 2. Append some nodes
ll.append(10)
ll.append(20)
ll.append(30)
print(f"After appending 10, 20, 30: {ll}")
print(f"Is list empty? {ll.is_empty()}")
print("-" * 20)
# 3. Prepend a node
ll.prepend(5)
print(f"After prepending 5: {ll}")
print("-" * 20)
# 4. Delete a node from the middle
ll.delete(20)
print(f"After deleting 20: {ll}")
print("-" * 20)
# 5. Delete the head node
ll.delete(5)
print(f"After deleting head (5): {ll}")
print("-" * 20)
# 6. Delete the tail node
ll.delete(30)
print(f"After deleting tail (30): {ll}")
print("-" * 20)
# 7. Try to delete a node that doesn't exist
ll.delete(99)
print(f"After trying to delete 99: {ll}")
print("-" * 20)
# 8. Find a node
found_node = ll.find(10)
if found_node:
    print(f"Found node: {found_node}")
else:
    print("Node not found.")

Linked List vs. Python list

It's important to understand when to use a linked list versus Python's built-in list.

Feature Linked List Python list (Dynamic Array)
Memory Usage Higher. Each node stores data and a pointer. Lower. Stores data in a contiguous block of memory.
Insertion/Deletion (Beginning) O(1). Just change the head pointer. O(n). All other elements must be shifted.
Insertion/Deletion (End) O(n) (unless you maintain a tail pointer). O(1) (Amortized).
Insertion/Deletion (Middle) O(n). Must find the location first. O(n). Must find the location and shift elements.
Accessing Element (Index i) O(n). Must traverse from the head. O(1). Direct memory access via index.
Cache Performance Poor. Data is scattered in memory. Excellent. Data is contiguous, so it's "cache-friendly".

Conclusion: You would almost always prefer Python's built-in list for its speed and simplicity. A linked list is primarily an academic data structure used to teach pointer manipulation and is the foundation for more complex structures like Stacks, Queues, and Graphs.

分享:
扫描分享到社交APP
上一篇
下一篇