(python)数据结构:双链表

关于单链表的实现和原理,可以查看我的上一篇博客:https://blog.csdn.net/hungpangzi/article/details/84439447

这里直接介绍双链表的实现:

1:创建一个表示节点的类(与单链表不同的是,双链表的每个节点有两个指针域:前驱和后继(头尾节点除外))

class Node:

    def __init__(self, data, prev = None, next = None):
        """
        :param data: 数据域中的数据
        :param prev: 指向前驱节点
        :param next: 指向后继节点
        """
        self._data = data;
        self._prev = prev;
        self._next = next;
    def __repr__(self):
        return (self._data);

2:初始化方法

class DDChainTable:
    def __init__(self):
        self._length = 0;  # 表示链表长度
        self._head = None; # 表示头部节点
        self._tail = None; # 表示尾部节点
        self._index_next = 0; # 生成器中的计数变量

3:判断链表是否为空

#  判断链表是否为空
    def _isEmpty(self):
        """
        :return:True|False
        """
        if self._length == 0:
            print("链表为空!!!");
            return True;
        else:
            return False

4:往链表末尾添加元素

# 往链表末尾添加元素
    def _append(self, DataOrNode):
        """
        :param DataOrNode: 数据或节点类的对象
        :return: None
        """
        item = None;
        #  将数据包装为Node类型的对象
        if isinstance(DataOrNode, Node):
            item = DataOrNode;
        else:
            item = Node(DataOrNode);
        if not self._head:
            #  如果头节点为空说明链表中无数据
            self._head = item;
            self._tail = item;
            self._length += 1;
        else:
            node = self._head;
            while node._next:
                node = node._next;
            item._prev = node;
            node._next = item;
            self._tail = item;
            self._length += 1;

5:判断传入的索引是否越界

#  判断用户传入的索引是否越界
    def _isIndexRight(self, index):
        if index < 0:
            if abs(index) > self._length:
                raise IndexError("索引越界!!!");
        else:
            if index >= self._length:
                raise IndexError("索引越界!!!");

6:根据索引删除元素

 #  根据索引删除节点
    def _delete(self, index):
        """
        :param index:要删除节点的索引。为负表示倒着查找。
        :return: None
        """
        if self._isEmpty():
            return ;
        self._isIndexRight(index);
        if index == 0:
            self._head = self._head._next;
            self._head._prev = None;
            self._length -= 1;
        elif index > 0:
            j = 0; # 辅助定位
            node = self._head; # 表示当前节点
            while node._next and j < index:
                node = node._next;
                j += 1;
            #  修改当前前驱节点和后继节点的指向
            node._prev._next = node._next;
            if node._next:
                node._next._prev = node._prev;
            elif not node._next:
                self._tail = node._prev;
            self._length -= 1;
        else:
            # 反向(效果与list中传入负数一样)
            if index == -1:
                self._tail._prev._next= None;
                self._tail = self._tail._prev;
                self._length -= 1;
            else:
                j = 1; # 辅助定位
                node =self._tail;
                while node._prev and j < abs(index):
                    node = node._prev;
                    j += 1;
                node._next._prev = node._prev;
                if node._prev:
                    node._prev._next = node._next;
                elif not node._prev:
                    self._head = node._next;
                self._length -= 1;

7:根据索引返回节点值

 #  根据索引返回节点的值
    def _getItem(self, index):
        """
        :param index: 要查找节点的索引
        :return: None
        """
        if self._isEmpty():
            return ;
        self._isIndexRight(index);
        if index < 0:
            j = 1; # 辅助定位
            node = self._tail;
            while node:
                if j == abs(index):
                    return node;
                else:
                    node = node._prev;
                    j += 1;
            return None;
        else:
            j = 0; # 辅助定位
            node = self._head;
            while node:
                if j == index:
                    return node;
                else:
                    node = node._next;
                    j += 1;
            return None;

8:根据节点值,返回该节点的索引

#  根据节点值返回该节点的索引
    def _getIndex(self, data):
        """
        :param data: 要查找位置的节点数据
        :return: index :该节点的索引(-1:表示未找到)
        """
        if self._isEmpty():
            return ;
        j = 0; # 辅助定位
        node = self._head; # 表示当前节点
        while node:
            if node._data == data:
                return j;
            else:
                node = node._next;
                j += 1;
        return -1;

9:修改指定位置的节点的值

 #  修改指定索引节点的值
    def _update(self, index, data):
        """
        :param index: 要修改节点的索引
        :param data: 修改后的值
        :return: None
        """
        if self._isEmpty():
            return;
        self._isIndexRight(index);
        # 开始修改
        node = self._getItem(index);
        if node:
            node._data = data;
        else:
            print("未找到该索引对应的节点。");

10:在指定位置插入节点

#  在指定位置插入节点
    def _insert(self, index, DataOrNode):
        """
        :param index: 位置
        :param DataOrNode: 数据
        :return: None
        """
        if self._isEmpty():
            return ;
        self._isIndexRight(index);
        #  包装数据
        item = None;
        if isinstance(DataOrNode, Node):
            item = DataOrNode;
        else:
            item = Node(DataOrNode);
        if index == 0:
            item._next = self._head;
            self._head_prev = item;
            self._head = item;
            self._length += 1;
        elif index > 0:
            j = 0; # 辅助定位
            node = self._head;
            while node._next and j < index:
                node = node._next;
                j += 1;
            item._prev = node._prev;
            node._prev._next = item;
            item._next = node;
            node._prev = item;
            self._length += 1;
        else:
            j = 1; # 辅助定位
            node = self._tail;
            while node._prev and j < abs(index):
                node = node._prev;
                j += 1;
            item._prev = node;
            item._next = node._next;
            if node._next:
                node._next._prev = item;
            if not node._next:
                self._tail = item
            node._next = item;
            self._length += 1;

11:模仿生成器,逐个返回节点值

#   模仿一个生成器,每次调用该方法,逐个返回节点
    def _next(self):
        """
        :return: 节点
        """
        if self._index_next < self._length:
            every_node = self._getItem(self._index_next);
            self._index_next += 1;
            yield (every_node);
        return None;

12:直接输出链表对象时,返回链表中所有数据组成的字符串

 #  当输出对象时,直接输出链表中的所有数据
    def __repr__(self):
        if self._length == 0:
            return("链表为空!!!");
        node = self._head;
        result = "";
        while node:
            result += node._data + " ";
            node = node._next;
        return result;

13:返回链表长度(len()方法)

#  当len(对象)时,返回链表长度
    def __len__(self):
        return (self._length);

完整代码可参考:https://github.com/shyorange/CommonlyUsedToolsProjects/blob/master/DoubleDirectionChainTable.py

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
双向循环链表是一种常见的数据结构,它与单向链表的区别在于每个节点都有两个指针,一个指向前一个节点,一个指向后一个节点。而循环链表则是在单向或双向链表的基础上,将最后一个节点的指针指向头节点,形成一个环。 以下是Python实现双向循环链表的示例代码: ```python class Node: def __init__(self, data): self.data = data self.prev = None self.next = None class DoublyLinkedList: def __init__(self): self.head = None self.tail = None def add_node(self, data): new_node = Node(data) if self.head is None: self.head = new_node self.tail = new_node self.head.prev = self.tail self.tail.next = self.head else: new_node.prev = self.tail self.tail.next = new_node new_node.next = self.head self.head.prev = new_node self.tail = new_node def display(self): current = self.head if self.head is None: print("List is empty") return else: print("Nodes of the doubly linked list:") print(current.data) while current.next != self.head: current = current.next print(current.data) dlist = DoublyLinkedList() dlist.add_node(1) dlist.add_node(2) dlist.add_node(3) dlist.display() ``` 上述代码中,我们定义了一个`Node`类来表示链表中的节点,每个节点包含一个数据项和两个指针,分别指向前一个节点和后一个节点。然后我们定义了一个`DoublyLinkedList`类来表示双向循环链表,其中包含一个头指针和一个尾指针。在`add_node`方法中,我们创建一个新节点,并将其添加到链表的末尾。在`display`方法中,我们遍历整个链表,并输出每个节点的数据项。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值