数据结构与算法(二)(Python版)

news/2024/4/26 16:46:15/文章来源:https://blog.csdn.net/m0_55854679/article/details/128793786

数据结构与算法(一)(Python版)

文章目录

  • 递归动规
    • 初识递归:数列求和
    • 递归三定律
    • 递归的应用:任意进制转换
    • 递归的应用:斐波那契数列
    • 递归调用的实现
    • 分治策略与递归
    • 优化问题和贪心策略
      • 找零兑换问题
      • 贪心算法和动态规划的区别
      • 贪心策略解决找零兑换问题
      • 找零兑换问题的递归解法
      • 找零兑换问题的动态规划解法
  • 排序与查找
    • 顺序查找算法及分析
      • 顺序查找:无序表查找
      • 顺序查找:有序表查找
    • 二分查找算法及分析
      • 递归算法实现二分查找
    • 二分查找与顺序查找的对比
    • 冒泡排序算法及分析
      • 冒泡排序优化
    • 冒泡排序与其他排序算法对比
    • 选择排序算法及分析
    • 插入排序算法及分析
    • 谢尔排序算法及分析
    • 归并排序算法及分析
    • 快速排序算法及分析

递归动规

递归是一种解决问题的方法,其精髓在于将问题分解为规模更小的相同问题,持续分解,直到问题规模小到可以用非常简单直接的方式来解决。递归的问题分解方式非常独特,其算法方面的明显特征就是:在算法流程中调用自身。

初识递归:数列求和

问题: 给定一个列表,返回所有数的和。列表中数的个数不定,需要一个循环和一个累加变量来迭代求和。

循环:

def listnum(numlist):thesum = 0for i in numlist:thesum = thesum + ireturn thesum
print(listnum([1,2,3,4,5]))

递归:
请添加图片描述

在这里插入图片描述
数列的和=“首个数”+“余下数列”的和

def digui(numlist):if len(numlist) == 1:return numlist[0]else:return  numlist[0] + digui(numlist[1:])
print(digui([1,2,3,4,5]))

递归三定律

在这里插入图片描述

递归的应用:任意进制转换

在这里插入图片描述

def jinzhi(n,base):convertstring = "0123456789ABCDEF"   ## 查表if n < base:return convertstring[n]else:return  jinzhi(n//base,base) + convertstring[n%base]
print(jinzhi(14,2))

递归的应用:斐波那契数列

def feibo(n):if n == 1 or n ==2:return 1else:return feibo(n-1) + feibo(n-2)return feibo[n]
print(feibo(3))

递归调用的实现

在这里插入图片描述
在调试递归算法程序的时候经常会碰到这样的错误:RecursionError,是因为递归的层数太多,系统调用栈容量有限。这时候要检查程序中是否忘记设置基本结束条件,导致无限递归,或者向基本结束条件演进太慢,导致递归层数太多,调用栈溢出。

Python内置的sys模块可以获取和调整最大递归深度。

在这里插入图片描述

分治策略与递归

在这里插入图片描述

优化问题和贪心策略

在这里插入图片描述

找零兑换问题

在这里插入图片描述

贪心算法和动态规划的区别

  1. 贪心算法每一步的最优解一定包含上一步的最优解,上一步之前的最优解则不作保留;动态规划全局最优解中不一定包含前一个局部最优解,因此需要记录之前的所有的局部最优解。
  2. 贪心不能保证最后解是最佳的,一般复杂度低;而动态规划本质是穷举法,可以保证结果是最佳的,复杂度高。

贪心策略解决找零兑换问题

在这里插入图片描述
因为我们每次都试图解决问题的尽量大的一部分对应到兑换硬币问题,就是每次以最多数量的最大面值硬币来迅速减少找零面值。

找零兑换问题的递归解法

在这里插入图片描述

def recMc(coinvaluelist,change):mincoins = changeif change in coinvaluelist:return 1           ##最小规模:直接返回else:for i in [c for c in coinvaluelist if c <= change]:numcoins = 1 + recMc(coinvaluelist,change - i) ##减小规模:每次减去一种硬币面值,挑选最小数量if numcoins < mincoins:mincoins = numcoinsreturn  mincoins
print(recMc([1,5,10,25],63))

递归解法虽然能解决问题,但其最大的问题是:极其低效。

在这里插入图片描述
对这个递归解法进行改进的关键就在于消除重复计算。
我们可以用一个表将计算过的中间结果保存起来,在计算之前查表看看是否已经计算过,这个算法的中间结果就是部分找零的最优解,在递归调用过程中已经得到的最优解被记录下来。在递归调用之前,先查找表中是否已有部分找零的最优解,如果有,直接返回最优解而不进行递归调用。如果没有,才进行递归调用。

在这里插入图片描述
改进后的解法,极大减少了递归调用次数对63分兑换硬币问题,仅仅需要221次递归调用是改进前的三十万分之一,瞬间返回。

找零兑换问题的动态规划解法

中间结果记录可以很好解决找零兑换问题实际上,这种方法还不能称为动态规划,而是叫做“memoization(记忆化/函数值缓存)”的技术提高了递归解法的性能。

动态规划算法采用了一种更有条理的方式来得到问题的解,找零兑换的动态规划算法从最简单的“1分钱找零”的最优解开始,逐步递加上去,直到我们需要的找零钱数。在找零递加的过程中,设法保持每一分钱的递加都是最优解,一直加到求解找零钱数,自然得到最优解。

递加的过程能保持最优解的关键是,其依赖于更少钱数最优解的简单计算,而更少钱数的最优解已经得到了。
问题的最优解包含了更小规模子问题的最优解,这是一个最优化问题能够用动态规划策略解决的必要条件。

在这里插入图片描述
在这里插入图片描述

排序与查找

顺序查找算法及分析

如果数据项保存在如列表这样的集合中,我们会称这些数据项具有线性或者顺序关系。在Python List中,这些数据项的存储位置称为下标【index】,这些下标都是有序的整数。通过下标,我们就可以按照顺序来访问和查找数据项,这种技术称为“顺序查找"。

要确定列表中是否存在需要查找的数据项,首先从列表的第1个数据项开始,按照下标增长的顺序,逐个比对数据项,如果到最后一个都未发现要查找的项,那么查找失败。

顺序查找:无序表查找

def sequentialsearch(alist,num):pos = 0found = False       ##注意found初始值为Falsewhile pos < len(alist) and not found:if alist[pos] == num:found =  Trueelse:pos += 1return foundtestlist = [11,22,33,44,55]
print(sequentialsearch(testlist,33))

时间复杂度为O(n)

顺序查找:有序表查找

当数据项存在时,比对过程与无序表完全相同。
不同之处在于,如果数据项不存在,比对可以提前结束。

在这里插入图片描述

def ordsequentialsearch(alist,num):pos = 0found = Falsestop = Falsewhile pos < len(alist) and not found and not stop:if alist[pos] == num:found = Trueelse:if alist[pos] > num:stop = Trueelse:pos += 1return foundtestlist = [1,2,3,4,6]
print(ordsequentialsearch(testlist,5))

实际上,就算法复杂度而言,仍然是O(n)。只是在数据项不存在的时候,有序表的查找能节省一些比对次数,但并不改变其数量级。

二分查找算法及分析

在这里插入图片描述

def binarysearch(alist,num):first = 0last = len(alist) - 1found = Falsewhile first <= last and not found:mid = (last + first) // 2if num == alist[mid]:found = Trueelse:if num > alist[mid]:first = mid + 1else:last = mid - 1return foundalist = [1,2,3,13,45,67]
print(binarysearch(alist,4))
print(binarysearch(alist,13))

二分查找算法实际上体现了解决问题的典型策略:分而治之,将问题分为若干更小规模的部分,通过解决每一个小规模部分问题,并将结果汇总得到原问题的解。

递归算法实现二分查找

def binarysearch(alist,num):if len(alist) == 0:return False           #递归结束条件else:mid = len(alist) // 2if alist[mid] == num:return Trueelse:if alist[mid] < num:return binarysearch(alist[mid+1:],num)else:return  binarysearch(alist[:mid-1],num)alist = [1,2,3,13,45,67]
print(binarysearch(alist,4))
print(binarysearch(alist,13))

在这里插入图片描述
所以二分法查找的算法复杂度是O(log n),实际代码中切片操作O(k)会使算法时间复杂度增加。

二分查找与顺序查找的对比

另外,虽然二分查找在时间复杂度上优于顺序查找,但也要考虑到对数据项进行排序的开销。如果一次排序后可以进行多次查找,那么排序的开销就可以摊薄。但如果数据集经常变动,查找次数相对较少,那么可能还是直接用无序表加上顺序查找来得经济。所以,在算法选择的问题上,光看时间复杂度的优劣是不够的,还需要考虑到实际应用的情况。

冒泡排序算法及分析

冒泡排序的算法思路在于对无序表进行多趟比较交换,每趟包括了多次两两相邻比较,并将逆序的数据项互换位置,最终能将本趟的最大项就位。经过n-1趟比较交换,实现整表排序【相当于一趟才能保证第一个数字最大项或者最小项就位】每趟的过程类似于“气泡”在水中不断上浮到水面的经过。

第1趟比较交换,共有n-1对相邻数据进行比较。一旦经过最大项,则最大项会一路交换到达最后一项。第2趟比较交换时,最大项已经就位,需要排序的数据减少为n-1,共有n-2对相邻数据进行比较,直到第n-1趟完成后,最小项一定在列表首位,就无需再处理了。

在这里插入图片描述

def bubblesort(alist):for passnum in range(len(alist)-1,0,-1):  for i in range(passnum):if alist[i] > alist[i+1]:# temp = alist[i]# alist[i] = alist[i+1]# alist[i+1] = tempalist[i],alist[i+1] = alist[i+1],alist[i]
alist = [54,26,93,17,77,31,44,55,20]
bubblesort(alist)
print(alist)

无序表初始数据项的排列状况对冒泡排序没有影响。算法过程总需要n-1趟,随着趟数的增加,比对次数逐步从n-1减少到1,并包括可能发生的数据项交换。比对的时间复杂度是O(n2)

最好的情况是列表在排序前已经有序,交换次数为0。最差的情况是每次比对都要进行交换,交换次数等于比对次数,平均情况则是最差情况的一半。交换次数也是O(n2)

冒泡排序优化

通过监测每趟比对是否发生过交换,可以提前确定排序是否完成,这也是其它多数排序算法无法做到的。

def bubblesort(alist):exchange = True          #注意exchange值的多次改变passnum = len(alist) - 1while passnum and  exchange:exchange = Falsefor i in range(passnum):if alist[i] > alist[i+1]:exchange = Truealist[i],alist[i+1] = alist[i+1],alist[i]passnum = passnum - 1alist = [54,26,93,17,77,31,44,55,20]
bubblesort(alist)
print(alist)

冒泡排序与其他排序算法对比

冒泡排序通常作为时间效率较差的排序算法,来作为其它算法的对比基准。其效率主要差在每个数据项在找到其最终位置之前,必须要经过多次比对和交换,其中大部分的操作是无效的。但有一点优势,就是无需任何额外的存储空间开销,适应性比较广,如链式也可以进行操作。

另外,通过监测每趟比对是否发生过交换,可以提前确定排序是否完成,这也是其它多数排序算法无法做到的。如果某趟比对没有发生任何交换,说明列表已经排好序,可以提前结束算法。

选择排序算法及分析

选择排序对冒泡排序进行了改进,保留了其基本的多趟比对思路,每趟都使当前最大项就位。但选择排序对交换进行了削减,相比起冒泡排序进行多次交换,每趟仅进行1次交换,记录最大项的所在位置,最后再跟本趟最后一项交换,选择排序的时间复杂度比冒泡排序稍优比对次数不变,还是o(n2),交换次数则减少为o(n)

在这里插入图片描述

def selectionsort(alist):for passnum in range(len(alist)-1,0,-1):positionmax = 0for i in range(1,passnum+1):   #这里因为设置最大位置初始值索引为0,所以需要从列表索引为1开始比较if alist[i] > alist[positionmax]:positionmax = ialist[positionmax],alist[passnum] = alist[passnum],alist[positionmax]alist = [54,26,93,17,77,31,44,55,20]
selectionsort(alist)
print(alist)

插入排序算法及分析

时间复杂度还是o(n2),插入排序的思想类似于整理扑克牌。第1趟,子列表仅包含第1个数据项,将第2个数据项作为“新项”插入到子列表的合适位置中,这样已排序的子列表就包含了2个数据项。第2趟,再继续将第3个数据项跟前2个数据项比对,并移动比自身大的数据项,空出位置来,以便加入到子列表中,经过n-1趟比对和插入,子列表扩展到全表,排序完成。

在这里插入图片描述

def insert(alist):for index in range(1,len(alist)):currentvalue = alist[index]   #插入项position = indexwhile position > 0 and alist[position] > currentvalue :alist[position] = alist[position - 1]position = position -1alist[position] = currentvaluealist = [11,23,31,24,56]insert(alist)
print(alist)

谢尔排序算法及分析

谢尔排序以插入排序为基础,对无序表进行“间隔”划分子列表,每个子列表都执行插入排序。随着子列表的数量越来越少,无序表的排序越来越接近有序,从而减少整体排序的比对次数。

在这里插入图片描述
最后一趟是标准的插入排序,但由于前面几趟已经将列表处理到接近有序,这一趟仅需少数几次移动即可完成。

在这里插入图片描述

归并排序算法及分析

归并排序是递归算法,思路是将数据表持续分裂为两半,对两半分别进行归并排序。
递归的基本结束条件是:数据表仅有1个数据项,自然是排好序的;缩小规模:将数据表分裂为相等的两半,规模减为原来的二分之一;调用自身:将两半分别调用自身排序,然后将分别排好序的两半进行归并,得到排好序的数据表。

在这里插入图片描述

def mergesort1(alist):if len(alist) > 1:    #基本结束条件mid = len(alist) //  2lefthalf = alist[:mid]righthalf = alist[mid:]mergesort1(lefthalf)    #递归调用mergesort1(righthalf)i = j = k = 0while i < len(lefthalf) and j < len(righthalf):    ## 拉链式交错把左右半部从小到大归并到结果列表if lefthalf[i] < righthalf[j]:alist[k] = lefthalf[i]i = i + 1else:alist[k] = righthalf[j]j = j + 1k = k + 1def mergesort2(alist):if len(alist) > 1:    #基本结束条件mid = len(alist) //  2lefthalf = alist[:mid]righthalf = alist[mid:]mergesort2(lefthalf)    #递归调用mergesort2(righthalf)i = j = k = 0while i < len(lefthalf):    #归并左半部剩余项alist[k] = lefthalf[i]i = i + 1k = k + 1while j < len(righthalf):  ##归并右边半部剩余项alist[k] = righthalf[i]j = j + 1k = k + 1def mergesort3(alist):# 递归结束条件if len(alist) <= 1:return alist# 分解问题,并递归调用mid = len(alist) // 2left = mergesort3(alist[:mid])right = mergesort3(alist[mid:])#合并左右半部,完成排序merged = []while left and right:if left[0] <= right[0]:merged.append(left.pop(0))else:merged.append(right.pop(0))merged.extend(right if right else left)return  mergedalist = [54,26,93,17,77,31,44,55,20]
mergesort1(alist)
print(alist)

将归并排序分为两个过程来分析:分裂和归并。

分裂的过程,借鉴二分查找中的分析结果,是对数复杂度,时间复杂度为O(log n)。归并的过程,相对于分裂的每个部分,其所有数据项都会被比较和放置一次,所以是线性复杂度,其时间复杂度是O(n)
综合考虑,每次分裂的部分都进行一次o(n)的数据项归并,总的时间复杂度为
o(nlog n)

最后,我们还是注意到两个切片操作。为了时间复杂度分析精确起见,可以通过取消切片操作,改为传递两个分裂部分的起始点和终止点,也是没问题的,只是算法可读性稍微牺牲一点点。我们注意到归并排序算法使用了额外1倍的存储空间用于归并,这个特性在对特大数据集进行排序的时候要考虑进去。

快速排序算法及分析

快速排序的思路是依据一个“中值”数据项来把数据表分为两半:小于中值的一半和大于中值的一半,然后每部分分别进行快速排序(递归)。如果希望这两半拥有相等数量的数据项,则应该找到数据表的“中位数”,但找中位数需要计算开销!要想没有开销,只能随意找一个数来充当“中值”。

快速排序的递归算法“递归三要素”如下基本结束条件:
数据表仅有1个数据项,自然是排好序的。
缩小规模:根据“中值”,将数据表分为两半,最好情况是相等规模的两半。
调用自身:将两半分别调用自身进行排序(排序基本操作在分裂过程中)。

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_72841.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

系列四、多表查询

一、多表关系 项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结 构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也存在着各种联系&#xff0c;基本上分为三种&#xff1a;一对多…

Sprng依赖注入(二):setter注入是如何工作的?

文章示例环境配置信息jdk版本:1.8开发工具&#xff1a;Intellij iDEA 2020.1springboot:2.3.9.RELEASE前言在Spring依赖注入&#xff08;一&#xff09;&#xff1a;字段注入的方式是如何工作的&#xff1f;中主要分享了Spring bean依赖注入方式中的字段注入方式及其工作过程&a…

基于Pytorch,从头开始实现Transformer(编码器部分)

Transformer理论部分参考知乎上的这篇文章 Transformer的Attention和Masked Attention部分参考知乎上的这篇文章 Transformer代码实现参考这篇文章&#xff0c;不过这篇文章多头注意力实现部分是错误的&#xff0c;需要注意。 完整代码放到github上了&#xff0c;链接 Trans…

联想小新 Air-14 2019IML电脑 Hackintosh 黑苹果efi引导文件

原文来源于黑果魏叔官网&#xff0c;转载需注明出处。硬件型号驱动情况主板Lenovo LNVNB161216处理器Intel Core i5-10210U / i7-10510U已驱动内存8GB DDR4 2666已驱动硬盘康佳KAK0500B128(128 GB/固志硬盘)已驱动显卡Intel UHD 620Nvidia GeForce MX250(屏蔽)无法驱动声卡Cone…

轮播图、阅读注册协议、网页时钟、随机点名、小米搜索框、轮播图点击切换——web APIs练习

目录 一、获取元素&#xff08;DOM&#xff09; 1. 随机轮播图案例 2. 阅读注册协议&#xff08;定时器间歇函数的应用&#xff09; 3. 轮播图定时器版 4. 网页时钟 二、事件基础&#xff08;DOM&#xff09; 1. 随机点名案例 2. 轮播图点击切换&#xff08;重点&#…

【计算机网络 -- 期末复习】

例题讲解 IP地址&#xff08;必考知识点&#xff09; 子网掩码 子网划分 第一栗&#xff1a; 子网划分题目的答案一般不唯一&#xff0c;我们主要采用下方的写法&#xff1a; 第二栗&#xff1a; 路由跳转 数据传输 CSMA/CD数据传输 2、比特率与波特率转换 四相位表示&am…

ElasticSearch 学习笔记总结(一)

文章目录一、 数据的 分类二、 ElasticSearch 介绍三、 ElasticSearch 搭建四、正排索引 和 倒排索引五、ES HTTP 索引 操作六、ES HTTP 文档 操作七、ES HTTP 查询数据1. 条件查询2. 分页查询3. 排序查询4. 多条件查询5. 全文检索 完全匹配 高亮显示6. 聚合查询八、 ES HTTP 映…

Scalable but Wasteful: Current State of Replication in the Cloud

文章目录ABSTRACT1 INTRODUCTION2 REPLICATION IN THE WILD3 CURRENT APPROACHES TO SCALING STATE MACHINE REPLICATION4 EFFICIENCY METRIC5 INEFFECTIVENESS OF CURRENT APPROACHES PER NEW METRIC6 CONCLUSION AND FUTURE DIRECTIONSABSTRACT 共识协议是部署在基于云的存储…

面试热点题:stl中vector与list的优缺点对比、以及list的迭代器与vector迭代器的区别

vector的优点 下标随机访问 vector的底层是一段连续的物理空间&#xff0c;所以支持随机访问尾插尾删效率高 跟数组类似&#xff0c;我们能够很轻易的找到最后一个元素&#xff0c;并完成各种操作cpu高速缓存命中率高 因为系统在底层拿空间的时候&#xff0c;是拿一段进cpu&am…

Linux:基于libevent读写管道代码,改进一下上一篇变成可以接收键盘输入

对上一篇进行改进&#xff0c;变成可以接收键盘输入&#xff0c;然后写入管道&#xff1a; 读端代码&#xff1a; #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <s…

乌卡时代的云成本管理:从0到1了解FinOps

在上一篇文章中&#xff0c;我们介绍了企业云业务的成本构成以及目前面临的成本困境&#xff0c;以及当前企业逐步转向 FinOps 的行业趋势&#xff0c;这篇文章我们将详细聊聊 FinOps&#xff0c;包括概念、重要性以及成熟度评价指标。 随着对云服务和供应商的使用越来越多&…

Sms多平台短信服务商系统~完成阿里云短信服务发送可自行配置

1.项目中引入Maven 阿里云地址 不同编程语言都有对应的SDK,你们下载自己需要的即可。 pom.xml中添加maven坐标 <!--阿里云短信服务--><dependency><groupId>com.aliyun</groupId><artifactId>alibabacloud-dysmsapi20170525</artifactId>…

【UE4 制作自己的载具】1-使用3dsmax制作载具

学习谌嘉诚课程所做笔记源视频链接&#xff1a;【虚幻4】UE4雪佛兰科迈罗汽车详细制作中文教程&#xff01;&#xff08;汽车骨骼绑定驾驶、动画蓝图&#xff09;汽车模型下载链接&#xff1a;https://pan.baidu.com/s/1ZH5gaAwckzRIZ0w6n0qvIA密码&#xff1a;19sj步骤&#x…

系列五、事务

一、事务简介 1.1、定义 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系 统提交或撤销操作请求&#xff0c;即这些操作要么同时成功&#xff0c;要么同时失败。 例如: 张三给李四转账1000块钱&#xff0c;张…

Codeforces Round #848 (Div. 2)(A~D)

A. Flip Flop Sum给出一个只有1和-1的数组&#xff0c;修改一对相邻的数&#xff0c;将它们变为对应的相反数&#xff0c;修改完后数组的和最大是多少。思路&#xff1a;最优的情况是修改一对-1&#xff0c;其次是一个1一个-1&#xff0c;否则修改两个1。AC Code&#xff1a;#i…

2023-02-22 学习记录--TS-邂逅TS(二)

TS-邂逅TS&#xff08;二&#xff09; 不积跬步&#xff0c;无以至千里&#xff1b;不积小流&#xff0c;无以成江海。&#x1f4aa;&#x1f3fb; 一、接口&#xff08;interface&#xff09; 在 ts 中&#xff0c;子类只能继承一个父类&#xff0c;不可多继承&#xff0c;但是…

学习国家颁布的三部信息安全领域法律,理解当前工作中的信息安全合规要求

目录三部信息安全领域的法律文件三部法律的角色定位与联系三部法律的适用范围三部法律的主要履职部门三部法律条文章节结构中的共性三部法律中的一些次重点章节网络安全法的重点章节数据安全法的重点章节个人信息保护法的重点章节关于工业和信息化部行政执法项目清单三部信息安…

ChatGPT这是要抢走我的饭碗?我10年硬件设计都有点慌了

前 言 呃……问个事儿&#xff0c;听说ChatGPT能写电路设计方案了&#xff0c;能取代初级工程师了&#xff1f;那我这工程师的岗位还保得住么&#xff1f;心慌的不行&#xff0c;于是赶紧打开ChatGPT问问它。 嘿&#xff0c;还整的挺客气&#xff0c;快来看看我的职业生涯是否…

非关系型数据库(mongodb)简单使用介绍

关系型数据库与非关系型数据库 关系型数据库有mysql、oracle、db2、sql server等&#xff1b; 关系型数据库特点&#xff1a;关系紧密&#xff0c;由表组成&#xff1b; 优点&#xff1a; 易于维护&#xff0c;都是使用表结构&#xff0c;格式一致&#xff1b; sql语法通用&a…

IP地理位置定位技术原理是什么

IP地理位置定位技术的原理是基于IP地址的网络通信原理和基础上的。它利用IP地址所包含的一些信息&#xff0c;如网络前缀和地址段&#xff0c;以及ISP的IP地址归属地数据库&#xff0c;来推测IP地址所对应的地理位置。具体来说&#xff0c;IP地址是由32位二进制数字组成的&…