(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

猜你喜欢

转载自blog.csdn.net/hungpangzi/article/details/84442969
今日推荐