python数据结构——链表总结

python数据结构——链表

单链表

概述

数据结构是计算机科学必须掌握的一门学科,在C语言中,可以使用“指针+结构体”来实现链表;而在python中,则可以采用“引用+类”来实现链表。

链表的定义:是一组数据项的集合,其中每个数据项都是一个节点的一部分,每个节点还包含指向下一个节点的链接。

链表的结构:data 为自定义的数据,next为下一个节点的地址,head为保存首位节点的地址:

在这里插入图片描述

img

单向链表实现:

单向链表(单链表)是链表的一种,它由节点组成,每个节点都包含下一个节点的指针。

示意图:

这里参考了关于链表的实现原理:传送门

在这里插入图片描述

单链表删除节点:

在这里插入图片描述

单链表增加节点:

单链表的特点是:节点的链接方向是单向的;相对于数组来说,单链表的的随机访问速度较慢,但是单链表删除/添加数据的效率很高。

class Node:
    def __init__(self,data):
        self.data = data
        self.next = None

class chain:
    def __init__(self):
        self.head = None

    def is_empty(self):
        return not self.head

    def length(self):
        count = 0
        cur = self.head
        while cur != None:
            count += 1
            cur = cur.next

        return count

    def add(self,data):
        node = Node(data)
        node.next = self.head
        self.head = node

    def append(self,data):
        cur = self.head
        while cur.next != None:
            cur = cur.next
        node = Node(data)
        cur.next = node

    def traverse(self):
        cur = self.head
        while cur != None:
            print(cur.data, end='-***-')
            cur = cur.next
        print()

    def insert(self,index,data):

        if index < 0:
            self.add(data)
        elif index > self.length() -1:
            self.append(data)
        else:
            cur = self.head
            for i in range(index - 1):
                cur = cur.next

            node = Node(data)
            node.next = cur.next
            cur.next = node

    def remove(self,data):
        cur = self.head
        pre = None
        while cur != None:
            if cur.data == data:
                if cur == self.head:
                    self.head = self.head.next
                    return
                pre.next = cur.next #前节点等于后节点
                return
            pre = cur
            cur = cur.next

    def search(self, data):
        cur = self.head
        while cur != None:
            if cur.data == data:
                print("数据%f存在于链表中" % cur.data)
                return True
            cur = cur.next
        print("数据不存在于链表中")
        return False

if __name__ == '__main__':
    chain = chain()
    chain.add(0)
    chain.traverse()
    for i in range(1,9):
        chain.append(i)
    chain.traverse()
    chain.length()
    chain.insert(3,100)
    chain.traverse()
    chain.remove(100)
    chain.traverse()
    chain.insert(-2,99)
    chain.traverse()
    chain.insert(100,1000)
    chain.traverse()
    chain.search(5)
>>>
0-***-
0-***-1-***-2-***-3-***-4-***-5-***-6-***-7-***-8-***-
0-***-1-***-2-***-100-***-3-***-4-***-5-***-6-***-7-***-8-***-
0-***-1-***-2-***-3-***-4-***-5-***-6-***-7-***-8-***-
99-***-0-***-1-***-2-***-3-***-4-***-5-***-6-***-7-***-8-***-
99-***-0-***-1-***-2-***-3-***-4-***-5-***-6-***-7-***-8-***-1000-***-
数据5.000000存在于链表中

单链表优化

class Node:
    def __init__(self, elem, next_=None):
        self.elem = elem
        self.next_ = None

class Llist:
    def __init__(self):
        self._head = None

    def is_empty(self):
        return self._head == None  #is和== 的差别

    def length(self):
        cur = self._head
        count = 0
        while cur != None:
            count += 1
            cur = cur.next_
        return count

    def add(self,data):  # 头元素的添加
        node = Node(data)
        node.next_=self._head
        self._head = node

    def append(self,data):
        if self.is_empty():
            self.add(data)
        else:
            cur = self._head
            while cur.next_ != None:
                cur = cur.next_

            node = Node(data)
            cur.next_ = node

    def insert(self, data, index):
        if index <= 0:
            self.add(data)
        elif index > self.length():
            self.append(data)
        else:
            cur = self._head
            for i in range(index-1):
                cur = cur.next_
            node = Node(data)
            node.next_ = cur.next_
            cur.next_ = node

    def remove_By_data(self,data):# 按照元素值删除
        if self.is_empty():
            print("None")
        else:
            cur = self._head
            pre = None
            while cur != None:
                if cur.elem == data:
                    if cur == self._head: # 头没有前节点
                        self._head = self._head.next_
                        return
                    pre.next_ = cur.next_
                pre = cur
                cur = cur.next_

    def remove_By_index(self,index): #按照位置删除

        if index ==0:
            self._head = self._head.next_

        else:
            cur = self._head
            pre = None
            for i in range(index):
                pre = cur
                cur = cur.next_
            pre.next_ = cur.next_


    def delet_all(self):
        if self.is_empty():
            return
        else:
            self._head = None

    def find_data(self, data):
        cur = self._head
        count = 0
        while cur != None:
            if cur.elem == data:
                print("数据:%.2f  坐标:%d"%(cur.elem,count))
                return
            count += 1
            cur = cur.next_

    def travle(self):
        cur = self._head
        while cur != None:
            print(cur.elem,end="-***-")
            cur = cur.next_
        print()


if __name__ == '__main__':
    chain = Llist()
    chain.add(1)
    chain.travle()
    chain.append(0)
    chain.travle()
    chain.insert(2,1)
    chain.travle()
    chain.find_data(2)
    chain.insert(3, 1)
    chain.find_data(2)
    chain.travle()
链表尾端插入优化

前面的单链表实现有一个缺点:尾端加入元素操作时的效率低下,因为每次都是从头端开始查找None指针
现在提出一种可行性设计,其中在表对象中加入一个表尾端引用域,只需要常量时间都能找到尾节点。
在这里插入图片描述

class UnorderedList(Llist):
    '''单向链表'''

    def __init__(self):
        # 头结点
        self._head = None
        # 尾结点(这是保证时间复杂度为O(1)的关键)
        # 因为始终实时跟踪尾结点,所以不需要遍历
        self.tail = None

    def add(self, val):
        '''这是向链表头部添加节点的方法'''
        temp = Node(val)
        temp.next = self._head
        self._head = temp
        # 如果链表是空的,表示这是第一个添加的节点
        # 那么它就应该是尾结点
        if self.tail is None:
            self.tail = self._head

    def append(self, val):
        '''这是向链表的尾部添加节点的方法'''
        # 如果现在链表还是空的
        # 那么append和add做的事情是一样的,所以直接调用add就行了
        if self.tail is None:
            self.add(val)
        # 如果当前链表不为空
        # 那么就把新节点拼接到链表的末尾
        else:
            self.tail.next = Node(val)
            self.tail = self.tail.next
            

循环单链表

class Node(object):
    def __init__(self, value):
        # 元素域
        self.value = value
        # 链接域
        self.next = None


class CircularLinkedListOneway(object):
    def __init__(self, node=None):
        # 构造非空链时,让其地址域指向自己
        if node:
            node.next = node
        self.__head = node

    def is_empty(self):
        # 头节点不为None则不为空
        return self.__head == None

    def __len__(self):
        count = 1
        cur = self.__head
        if self.is_empty():
            return 0
        while cur.next != self.__head:
            count += 1
            cur = cur.next
        return count

    def traversal(self):
        if self.is_empty():
            return
        cur = self.__head
        while cur.next != self.__head:
            print(cur.value)
            cur = cur.next
        # 退出循环时,cur正是尾节点
        print(cur.value)

    def add(self, value):
        """头插法"""
        node = Node(value)
        if self.is_empty():
            self.__head = node
            self.__head.next = self.__head
            return
        cur = self.__head
        while cur.next != self.__head:
            cur = cur.next
        # 新节点的next指针指向原头节点
        node.next = self.__head
        # 将新节点指向头节点
        self.__head = node
        # 尾节点next指针指向新头节点
        cur.next = self.__head

    def append(self, value):
        node = Node(value)
        cur = self.__head
        if self.is_empty():
            self.__head = node
            self.__head.next = self.__head
            return
        while cur.next != self.__head:
            cur = cur.next
        node.next = cur.next
        cur.next = node

    def insert(self, pos, value):
        if pos <= 0:
            self.add(value)
        elif pos > len(self) - 1:
            self.append(value)
        else:
            node = Node(value)
            cur = self.__head
            count = 0
            while count < pos - 1:
                count += 1
                cur = cur.next
            node.next = cur.next
            cur.next = node

    def search(self, value):
        if self.is_empty():
            return False
        cur = self.__head
        while cur.next != self.__head:
            if cur.value == value:
                return True
            else:
                cur = cur.next
        # 别忘了while循环外的尾节点
        if cur.value == value:
            return True
        return False

    def remove(self, value):
        cur = self.__head
        prior = None
        if self.is_empty():
            return
        while cur.next != self.__head:
            # 待删除节点如果找到
            if cur.value == value:
                # 待删除节点在头部
                if cur == self.__head:
                    rear = self.__head
                    while rear.next != self.__head:
                        rear = rear.next
                    self.__head = cur.next
                    rear.next = self.__head
                # 待删除节点在中间
                else:
                    prior.next = cur.next # 这里不是跳出循环的break,而是退出函数的return哦,因为已经处理完毕了
                return
            # 如果还没找到
            else:
                prior = cur
                cur = cur.next
        # 待删除节点在尾部
        if cur.value == value:
            # 如果链表中只有一个元素,则此时prior为None,Next属性就会报错
            # 此时直接使其头部元素为None即可
            if cur == self.__head:
                self.__head = None
                return
            prior.next = cur.next

if __name__ == '__main__':
    chain = CircularLinkedListOneway()
    chain.add(1)
    chain.append(2)
    chain.traversal()
   
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值