数据结构——链表

单链表


class Node:
    next = None
    data = None

    def __init__(self, nodeData):
        self.data = nodeData


class List:
    head = None
    size = 0

    def __init__(self):
        self.size = 0
        self.head = None

    # 遍历链表
    def a(self):
        print("avx")

    def printlist(self):
        p = self.head
        while p is not None:
            print(p.data)
            p = p.next
        print("——————————————————————————————————————")

    def insertlink(self, a, newdata):
        newnode = Node(newdata)
        if self.size == 0:
            print("The link is none")
            self.head = newnode
            self.size = self.size + 1
        else:
            p = self.head
            while (p is not None) and (p.data != a):
                p = p.next
            if p.next is None:
                p.next = newnode
                self.size = self.size + 1
            else:
                newnode.next = p.next
                p.next = newnode
                self.size = self.size + 1

    # 删除链表中的节点
    def deldata(self, a):
        if self.size == 0:
            print("The link is none")
        elif self.size == 1:
            self.head = None
            self.size = self.size - 1
        else:
            p = self.head
            while (p is not None) and (p.data != a):
                q = p
                p = p.next
            if p is None:
                print("Can't find a")
            elif p == self.head:
                self.head = p.next
            elif p.data == a and p.next is not None:
                q.next = q.next.next
                self.size = self.size - 1
            else:
                q.next = None
                self.size = self.size - 1

    # 修改链表中的指定节点
    def updatelink(self, a, b):
        p = self.head
        print(p.data)
        while (p is not None) and (p.data != a):
            p = p.next
        if p is None:
            print("Can't find a")
        else:
            p.data = b


if __name__ == "__main__":
    p = List()
    p.insertlink(1, 1)
    p.insertlink(1, 2)
    p.insertlink(1, 3)
    p.insertlink(1, 4)
    print("_________________________---insertlink")
    p.printlist()
    print("_________________________--chalink")
    p.updatelink(2, 5)
    p.printlist()
    print("___________________________-----dellink")
    p.deldata(5)
    p.printlist()

循环链表


class Node(object):
    def __init__(self, item):
        self.item = item  # 节点数值
        self.prev = None  # 用于指向前一个元素
        self.next = None  # 用于指向后一个元素


# 双向循环链表
class DoubleCircleLinkList(object):
    def __init__(self):
        self.__head = None  # 初始化的时候头节点设为空、

    # 判断链表是否为空,head为None 的话则链表是空的
    def is_empty(self):
        return self.__head is None

    # 头部添加元素的方法
    def add(self, item):
        node = Node(item)  # 新建一个节点node 里面的值是item
        # 如果链表是空的,则node的next和prev都指向自己(因为是双向循环),head指向node
        if self.is_empty():
            self.__head = node
            node.next = node
            node.prev = node
        # 否则链表不空
        else:
            node.next = self.__head  # node的next设为现在的head
            node.prev = self.__head.prev  # node的prev 设为现在head的prev
            self.__head.prev.next = node  # 现在head的前一个元素的next设为node
            self.__head.prev = node  # 现在head的前驱 改为node
            self.__head = node  # 更改头部指针

    # 尾部添加元素方法
    def append(self, item):
        # 如果当前链表是空的 那就调用头部插入方法
        if self.is_empty():
            self.add(item)
        # 否则链表不为空
        else:
            node = Node(item)  # 新建一个节点node
            # 因为是双向循环链表,所以head的prev其实就是链表的尾部
            node.next = self.__head  # node的下一个设为头
            node.prev = self.__head.prev  # node的前驱设为现在头部的前驱
            self.__head.prev.next = node  # 头部前驱的后继设为node
            self.__head.prev = node  # 头部自己的前驱改为node

    # 获得链表长度 节点个数
    def length(self):
        # 如果链表是空的 就返回0
        if self.is_empty():
            return 0
        # 如果不是空的
        else:
            cur = self.__head  # 临时变量cur表示当前位置 初始化设为头head
            count = 1  # 设一个计数器count,cur每指向一个节点,count就自增1  目前cur指向头,所以count初始化为1
            # 如果cur.next不是head,说明cur目前不是最后一个元素,那么count就1,再让cur后移一位
            while cur.next is not self.__head:
                count += 1
                cur = cur.next
            # 跳出循环说明所有元素都被累加了一次 返回count就是一共有多少个元素
            return count

    # 遍历链表的功能
    def travel(self):
        # 如果当前自己是空的,那就不遍历
        if self.is_empty():
            return
        # 链表不空
        else:
            cur = self.__head  # 临时变量cur表示当前位置,初始化为链表的头部
            # 只要cur的后继不是头说明cur不是最后一个节点,我们就输出当前值,并让cur后移一个节点
            while cur.next is not self.__head:
                print(cur.item, end=" ")
                cur = cur.next
            # 当cur的后继是head的时候跳出循环了,最后一个节点还没有打印值 在这里打印出来
            print(cur.item)

    # 置顶位置插入节点
    def insert(self, pos, item):
        # 如果位置<=0 则调用头部插入方法
        if pos <= 0:
            self.add(item)
        # 如果位置是最后一个或者更大 就调用尾部插入方法
        elif pos > self.length() - 1:
            self.append(item)
        # 否则插入位置就是链表中间
        else:
            index = 0  # 设置计数器,用于标记我们后移了多少步
            cur = self.__head  # cur标记当前所在位置
            # 让index每次自增1 ,cur后移,当index=pos-1的时候说明cur在要插入位置的前一个元素,这时候停下
            while index < pos - 1:
                index += 1
                cur = cur.next
            # 跳出循环,cur在要插入位置的前一个元素,将node插入到cur的后面
            node = Node(item)  # 新建一个节点
            node.next = cur.next  # node的后继设为cur的后继
            node.prev = cur  # node的前驱设为cur
            cur.next.prev = node  # cur后继的前驱改为node
            cur.next = node  # cur后继改为node

    # 删除节点操作
    def remove(self, item):
        # 如果链表为空 直接不操作
        if self.is_empty():
            return
        # 链表不为空
        else:
            cur = self.__head  # 临时变量标记位置,从头开始
            # 如果头结点就是 要删除的元素
            if cur.item == item:
                # 如果只有一个节点 链表就空了 head设为None
                if self.length() == 1:
                    self.__head = None
                # 如果多个元素
                else:
                    self.__head = cur.next  # 头指针指向cur的下一个
                    cur.next.prev = cur.prev  # cur后继的前驱改为cur的前驱
                    cur.prev.next = cur.next  # cur前驱的后继改为cur的后继
            # 否则 头节点不是要删除的节点 我们要向下遍历
            else:
                cur = cur.next  # 把cur后移一个节点
                # 循环让cur后移一直到链表尾元素位置,期间如果找得到就删除节点,找不到就跳出循环,
                while cur is not self.__head:
                    # 找到了元素cur就是要删除的
                    if cur.item == item:
                        cur.prev.next = cur.next  # cur的前驱的后继改为cur的后继
                        cur.next.prev = cur.prev  # cur的后继的前驱改为cur的前驱
                    cur = cur.next

    # 搜索节点是否存在
    def search(self, item):
        # 如果链表是空的一定不存在
        if self.is_empty():
            return False
        # 否则链表不空
        else:
            cur = self.__head  # 设置临时cur从头开始
            # cur不断后移,一直到尾节点为止
            while cur.next is not self.__head:
                # 如果期间找到了就返回一个True 结束运行
                if cur.item == item:
                    return True
                cur = cur.next
            # 从循环跳出来cur就指向了尾元素 看一下为元素是不是要找的 是就返回True
            if cur.item == item:
                return True
            # 所有元素都不是 就返回False 没找到
            return False


if __name__ == "__main__":
    dlcl = DoubleCircleLinkList()
    print(dlcl.search(7))
    dlcl.travel()
    dlcl.remove(1)
    print(dlcl.length())
    print(dlcl.is_empty())
    dlcl.append(55)
    print(dlcl.search(55))
    dlcl.travel()
    dlcl.remove(55)
    dlcl.travel()
    print(dlcl.length())
    dlcl.add(3)
    print(dlcl.is_empty())
    dlcl.travel()
    dlcl.add(4)
    dlcl.add(5)
    dlcl.append(6)
    dlcl.insert(-10, 1)
    dlcl.travel()
    print(dlcl.length())
    dlcl.remove(6)
    dlcl.travel()

    print(dlcl.search(7))
    dlcl.append(55)
    dlcl.travel()

双向链表​​​​


class Node:
    data = None
    nextnode = None
    prenode = None

    def __init__(self, data):
        self.data = data


class PersonChan:
    size = 0
    head = None
    tail = None

    def __init__(self):
        self.head = None
        self.tail = None
        self.size = 0

    # 增加节点
    def add_node(self, a):
        newnode = Node(a)
        if self.head is None:
            self.head = newnode
            self.head.prenode = None
            self.tail = newnode
            self.tail.prenode = None
            self.tail.nextnode = None
            self.size = self.size + 1
        else:
            temp = self.head
            while temp.nextnode is not None:  # 返回尾节点tail
                temp = temp.nextnode
            temp.nextnode = newnode
            self.tail = newnode
            self.tail.prenode = temp
            self.tail.nextnode = None
            self.size = self.size + 1

    # 在查找到的a后面增加节点
    def ins_node(self, a, b):
        newnode = Node(b)
        if self.head is None:
            self.head = newnode
            self.tail = newnode
            print("Insert success:", newnode.data)
            self.size = self.size + 1
        else:
            temp = self.head
            while (temp is not None) & (temp.data != a):
                temp = temp.nextnode
            if temp.nextnode is None:
                temp.nextnode = newnode
                self.tail = newnode
                self.tail.prenode = temp
                self.tail.nextnode = None
                temp = None
                print("Insert success:", newnode.data)
                self.size = self.size + 1
            else:
                newnode.prenode = temp
                newnode.nextnode = temp.nextnode
                temp.nextnode = newnode
                print("Insert success:", newnode.data)
                self.size = self.size + 1

    # 删除节点
    def del_node(self, a):
        if self.head is None:
            pass
        elif self.head.data == a:
            if self.size == 1:
                self.head = None
                self.tail = None
                self.size = self.size - 1
            else:
                self.head = self.head.nextnode
                self.size = self.size - 1
        else:
            temp = self.head.nextnode
            while (temp is not None) and (temp.data != a):
                temp = temp.nextnode
            p = temp.prenode
            if temp is not None:
                if temp.nextnode is None:

                    self.tail = p
                    self.tail.nextnod = None
                else:
                    p.nextnode = temp.nextnode
                    temp = None
                self.size = self.size - 1
                print("Delete is success:", a)

    def listall(self):  # 正序排列
        if self.size == 0:
            print("No data in the list")
        else:
            temp = self.head
            while (temp is not None):
                print(temp.data)
                temp = temp.nextnode

    def lista(self):  # 倒序排列
        if self.size == 0:
            print("No data in the list")
        temp = self.tail
        while temp is not None:
            print(temp.data)
            temp = temp.prenode


if __name__ == '__main__':
    link = PersonChan()
    link.add_node(1)
    link.add_node(2)
    link.add_node(3)
    link.add_node(4)
    link.listall()
    print("The list's size is:", link.size)
    link.lista()

 


单链表反转


 

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


def rev(link):
    pre = link
    cur = link.next
    pre.next = None
    while cur:
        temp = cur.next
        cur.next = pre
        pre = cur
        cur = temp
    return pre


if __name__ == '__main__':
    link = Node(1, Node(2, Node(3, Node(4, Node(5, Node(6, Node(7, Node(8, Node(9)))))))))
    root = rev(link)
    while root:
        print(root.data)
        root = root.next

两个有序的链表合并为一个有序链表


class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None


class Solution:
    def mergeTwoLists(self, l1, l2):

        if not l1:
            return l2
        if not l2:
            return l1
        if l1.val <= l2.val:
            ret = l1
            ret.next = self.mergeTwoLists(l1.next, l2)
        else:
            ret = l2
            ret.next = self.mergeTwoLists(l1, l2.next)
        return ret

求链表的中间结点


class Solution:
    def middleNode(self, head):

        count = 0
        res = {}
        while head != None:
            count += 1
            res[count] = head
            head = head.next

        j = math.ceil((count - 1) / 2) + 1
        return res[j]

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1 目标检测的定义 目标检测(Object Detection)的任务是找出图像中所有感兴趣的目标(物体),确定它们的类别和位置,是计算机视觉领域的核心问题之一。由于各类物体有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具有挑战性的问题。 目标检测任务可分为两个关键的子任务,目标定位和目标分类。首先检测图像中目标的位置(目标定位),然后给出每个目标的具体类别(目标分类)。输出结果是一个边界框(称为Bounding-box,一般形式为(x1,y1,x2,y2),表示框的左上角坐标和右下角坐标),一个置信度分数(Confidence Score),表示边界框中是否包含检测对象的概率和各个类别的概率(首先得到类别概率,经过Softmax可得到类别标签)。 1.1 Two stage方法 目前主流的基于深度学习的目标检测算法主要分为两类:Two stage和One stage。Two stage方法将目标检测过程分为两个阶段。第一个阶段是 Region Proposal 生成阶段,主要用于生成潜在的目标候选框(Bounding-box proposals)。这个阶段通常使用卷积神经网络(CNN)从输入图像中提取特征,然后通过一些技巧(如选择性搜索)来生成候选框。第二个阶段是分类和位置精修阶段,将第一个阶段生成的候选框输入到另一个 CNN 中进行分类,并根据分类结果对候选框的位置进行微调。Two stage 方法的优点是准确度较高,缺点是速度相对较慢。 常见Tow stage目标检测算法有:R-CNN系列、SPPNet等。 1.2 One stage方法 One stage方法直接利用模型提取特征值,并利用这些特征值进行目标的分类和定位,不需要生成Region Proposal。这种方法的优点是速度快,因为省略了Region Proposal生成的过程。One stage方法的缺点是准确度相对较低,因为它没有对潜在的目标进行预先筛选。 常见的One stage目标检测算法有:YOLO系列、SSD系列和RetinaNet等。 2 常见名词解释 2.1 NMS(Non-Maximum Suppression) 目标检测模型一般会给出目标的多个预测边界框,对成百上千的预测边界框都进行调整肯定是不可行的,需要对这些结果先进行一个大体的挑选。NMS称为非极大值抑制,作用是从众多预测边界框中挑选出最具代表性的结果,这样可以加快算法效率,其主要流程如下: 设定一个置信度分数阈值,将置信度分数小于阈值的直接过滤掉 将剩下框的置信度分数从大到小排序,选中值最大的框 遍历其余的框,如果和当前框的重叠面积(IOU)大于设定的阈值(一般为0.7),就将框删除(超过设定阈值,认为两个框的里面的物体属于同一个类别) 从未处理的框中继续选一个置信度分数最大的,重复上述过程,直至所有框处理完毕 2.2 IoU(Intersection over Union) 定义了两个边界框的重叠度,当预测边界框和真实边界框差异很小时,或重叠度很大时,表示模型产生的预测边界框很准确。边界框A、B的IOU计算公式为: 2.3 mAP(mean Average Precision) mAP即均值平均精度,是评估目标检测模型效果的最重要指标,这个值介于0到1之间,且越大越好。mAP是AP(Average Precision)的平均值,那么首先需要了解AP的概念。想要了解AP的概念,还要首先了解目标检测中Precision和Recall的概念。 首先我们设置置信度阈值(Confidence Threshold)和IoU阈值(一般设置为0.5,也会衡量0.75以及0.9的mAP值): 当一个预测边界框被认为是True Positive(TP)时,需要同时满足下面三个条件: Confidence Score > Confidence Threshold 预测类别匹配真实值(Ground truth)的类别 预测边界框的IoU大于设定的IoU阈值 不满足条件2或条件3,则认为是False Positive(FP)。当对应同一个真值有多个预测结果时,只有最高置信度分数的预测结果被认为是True Positive,其余被认为是False Positive。 Precision和Recall的概念如下图所示: Precision表示TP与预测边界框数量的比值 Recall表示TP与真实边界框数量的比值 改变不同的置信度阈值,可以获得多组Precision和Recall,Recall放X轴,Precision放Y轴,可以画出一个Precision-Recall曲线,简称P-R
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值