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
    评论
哈希表是一种高效的数据结构,可以用来存储和查找键值对。其中,哈希函数将键映射到一个特定的桶中,每个桶中存储一组键值对。在哈希表中,如果两个键被映射到同一个桶中,就会发生碰撞。为了解决这个问题,可以使用链表法。 链表法是一种解决哈希表碰撞问题的方法。具体来说,对于哈希表中的每个桶,可以使用一个链表来存储所有映射到该桶的键值对。如果发生碰撞,只需要将新的键值对添加到链表的末尾即可。 下面是一个使用链表法实现哈希表的示例代码: ```python class Node: def __init__(self, key, value): self.key = key self.value = value self.next = None class HashTable: def __init__(self, capacity): self.capacity = capacity self.buckets = [None] * capacity def hash_function(self, key): return hash(key) % self.capacity def put(self, key, value): index = self.hash_function(key) node = self.buckets[index] while node: if node.key == key: node.value = value return node = node.next new_node = Node(key, value) new_node.next = self.buckets[index] self.buckets[index] = new_node def get(self, key): index = self.hash_function(key) node = self.buckets[index] while node: if node.key == key: return node.value node = node.next return None def remove(self, key): index = self.hash_function(key) node = self.buckets[index] prev = None while node: if node.key == key: if prev: prev.next = node.next else: self.buckets[index] = node.next return prev = node node = node.next ``` 在这个示例中,我们定义了一个Node类来表示哈希表中的每个节点,每个节点包含一个键、一个值和一个指向下一个节点的指针。我们还定义了一个HashTable类来实现哈希表,其中包含一个桶数组和一些基本的操作方法,如put、get和remove。 在put方法中,我们首先使用哈希函数计算出键的索引,然后遍历桶中的链表,查找该键是否已经存在于哈希表中。如果找到了该键,我们只需要更新其对应的值即可。否则,我们创建一个新的节点,并将其添加到链表的开头。 在get方法中,我们同样使用哈希函数计算出键的索引,然后遍历桶中的链表,查找该键的值。如果找到了该键,我们返回其对应的值。否则,返回None。 在remove方法中,我们首先使用哈希函数计算出键的索引,然后遍历桶中的链表,查找该键。如果找到了该键,我们将其从链表中删除即可。 总的来说,链表法是一种简单且常用的哈希表解决碰撞问题的方法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值