数据结构与算法(python):链表基本定义与操作

文章目录

    • 1、介绍
    • 2、单链表
    • 3、双向链表

1、介绍

根据数据存储结构,可以将数据结构划分为:

  1. 顺序存储
  2. 链式存储
  3. 索引存储
  4. 散列存储

之前介绍过的顺序表即采用顺序存储结构,这里介绍链式存储结构。主要包括单链表双链表


2、单链表

以下为通过 p y t h o n 3 python3 python3 实现的单链表代码

# -*- coding: utf-8 -*-

# 定义单链表结点
class Node(object):
    def __init__(self, value=None, next=None):   # root 节点默认都是 None
        self.value = value
        self.next = next
# 定义循环单链表结点
class Node(object):
    def __init__(self, value=None, next=None):   # root 节点默认都是 None
        self.value = value
        self.next = next

定义单链表类

# 定义单链表
class LinkedList(object):
    """ 单链表 ADT
    [root] -> [node0] -> [node1] -> [node2]
    """
    
    def __init__(self, maxsize=None):
        """
        :param maxsize: int or None, 如果是 None,无限扩充
        """
        self.maxsize = maxsize
        self.root = Node()        # 默认根结点指向 None
        self.tailnode = None      # 尾结点
        self.length = 0           # 链表长度

    def __len__(self):
        return self.length        # 返回链表长度

    def append(self, value):      # 尾插法,时间复杂度O(1)
        if self.maxsize != None and len(self) >= self.maxsize:
            raise Exception('LinkedList is full!')
        node = Node(value)        # 构造新结点
        tailnode = self.tailnode
        if tailnode is None:      # 空链表追加到根结点后
            self.root.next = node
        else:                     # 追加到尾结点的后边,并更新尾结点和链表长度
            tailnode.next = node
        # 若为循环链表,此处加上:node.next = self.root.next
        self.tailnode = node
        self.length += 1

    def appendleft(self, value):  # 头插法
        if self.maxsize != None and len(self) >= self.maxsize:
            raise Exception('LinkedList is Full')
        node = Node(value)
        if self.tailnode == None: # 原链表为空,则修改尾结点
            self.tailnode = node
           
        # 若为循环链表,此处加上:self.tailnode.next = node
        node.next = self.root.next
        self.root.next = node
        self.length += 1

    def __iter__(self):
        for node in self.iter_node():
            yield node.value

    def iter_node(self):
        """遍历从头结点到尾结点"""
        curnode = self.root.next
        while curnode != self.tailnode:    # 从第一个节点开始遍历
            yield curnode
            curnode = curnode.next         # 移动到下一个节点
        if curnode is not None:
            yield curnode

    def remove(self, value):    # 删除结点 O(n)
        """ 删除包含值的第一个节点
        :param value:
        """
        prevnode = self.root
        for curnode in self.iter_node():
            if curnode.value == value:
                prevnode.next = curnode.next
                if curnode is self.tailnode:    # 注意更新尾结点
                    self.tailnode = prevnode
                """若为循环链表,此处加上:
                if curnode is self.root.next:
                	self.tailnode.next = self.root.next
                """
                del curnode
                self.length -= 1
                return 1                        # 删除成功
            else:
                prevnode = curnode
        return -1                               # 删除失败

    def find(self, value):    # O(n)
        """ 查找结点,返回序号,从 0 开始
        :param value:
        """
        index = 0
        for node in self.iter_node():
            if node.value == value:
                return index
            index += 1
        return -1                 # 没找到

    def popleft(self):            # O(1)
        """ 删除第一个链表节点
        """
        if self.root.next == None:
            raise Exception('pop from empty LinkedList')
        headnode = self.root.next
        self.root.next = headnode.next
        # 若为循环链表,此处加上:self.tailnode.next = self.root.next
        self.length -= 1
        value = headnode.value

        if self.tailnode == headnode:   # 单节点删除处理
            self.tailnode = None
        del headnode
        return value

    def clear(self): 
    	"""清空链表"""
        for node in self.iter_node():
            del node
        self.root.next = None
        self.length = 0
        self.tailnode = None

    def reverse(self):
        """反转链表"""
        curnode = self.root.next
        prevnode = None   # 若为循环链表,此处改为:prevnode = self.tailnode
        self.tailnode = curnode         # 更新 tailnode

        while curnode:
            nextnode = curnode.next     # 记录下一结点
            curnode.next = prevnode     # 指向前一结点

            if nextnode is None:        # 尾结点变头结点
                self.root.next = curnode
                
            prevnode = curnode
            curnode = nextnode
        """若为循环链表,以上循环改为:
		while curnode.next is not self.root.next:
			nextnode = curnode.next     # 记录下一结点
            curnode.next = prevnode     # 指向前一结点

            prevnode = curnode
            curnode = nextnode
		curnode.next = prevnode     # 指向前一结点
		self.root.next = curnode    # 尾结点变头结点
		"""
  1. 插入结点示意图
    数据结构与算法(python):链表基本定义与操作_第1张图片
    数据结构与算法(python):链表基本定义与操作_第2张图片
  2. 删除结点示意图
    数据结构与算法(python):链表基本定义与操作_第3张图片
    数据结构与算法(python):链表基本定义与操作_第4张图片

3、双向链表

首先定义双向链表结点

class Node(object):

    def __init__(self, value=None, prev=None, next=None):
        self.value, self.prev, self.next = value, prev, next

定义双向链表

class DoubleLinkedList(object):
    """双向循环链表 ADT
    """

    def __init__(self, maxsize=None):
        self.maxsize = maxsize
        node = Node()
        node.next, node.prev = node, node
        self.root = node
        self.length = 0

    def __len__(self):     # 返回链表长度
        return self.length

    def headnode(self):    # 头结点
        return self.root.next

    def tailnode(self):    # 尾结点
        return self.root.prev

    def append(self, value):    # O(1), 尾插法
        if self.maxsize is not None and len(self) >= self.maxsize:
            raise Exception('LinkedList is Full')
        node = Node(value=value)
        tailnode = self.tailnode() or self.root

        tailnode.next = node
        node.prev = tailnode
        node.next = self.root
        self.root.prev = node
        self.length += 1

    def appendleft(self, value):           # 头插法
        if self.maxsize is not None and len(self) >= self.maxsize:
            raise Exception('LinkedList is Full')
        node = Node(value=value)
        if self.root.next is self.root:    # 空链表
            node.next = self.root
            node.prev = self.root
            self.root.next = node
            self.root.prev = node
        else:
            node.prev = self.root
            node.next = self.root.next
            self.root.next.prev = node
            node.prev.next = node
        self.length += 1

    def remove(self, node):      # O(1),传入node 而不是 value
        """remove
        :param node
        """
        if node is self.root:
            return
        else: 
            node.prev.next = node.next
            node.next.prev = node.prev
        self.length -= 1
        return node

    def iter_node(self):
        if self.root.next is self.root:
            return
        curnode = self.root.next
        while curnode.next is not self.root:
            yield curnode
            curnode = curnode.next
        yield curnode

    def __iter__(self):
        for node in self.iter_node():
            yield node.value

    def iter_node_reverse(self):
        """相比单链表独有的反序遍历"""
        if self.root.prev is self.root:
            return
        curnode = self.root.prev
        while curnode.prev is not self.root:
            yield curnode
            curnode = curnode.prev
        yield curnode

注意:链表在进行插入和删除操作时,需要注意顺序,以下为双向链表插入删除示意图:

  1. 插入示意图数据结构与算法(python):链表基本定义与操作_第5张图片
  2. 删除示意图
    数据结构与算法(python):链表基本定义与操作_第6张图片

你可能感兴趣的:(数据结构与算法,Python)