搜索
首页后端开发Python教程基于python的七种经典排序算法的详细介绍

一、排序的基本概念和分类

所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。排序算法,就是如何使得记录按照要求排列的方法。

排序的稳定性:

经过某种排序后,如果两个记录序号同等,且两者在原无序记录中的先后秩序依然保持不变,则称所使用的排序方法是稳定的,反之是不稳定的。

内排序和外排序

内排序:排序过程中,待排序的所有记录全部放在内存中

外排序:排序过程中,使用到了外部存储。

通常讨论的都是内排序。

影响内排序算法性能的三个因素:

 时间复杂度:即时间性能,高效率的排序算法应该是具有尽可能少的关键字比较次数和记录的移动次数

 空间复杂度:主要是执行算法所需要的辅助空间,越少越好。

 算法复杂性。主要是指代码的复杂性。

根据排序过程中借助的主要操作,可把内排序分为:

 插入排序

 交换排序

 选择排序

 归并排序

按照算法复杂度可分为两类:

 简单算法:包括冒泡排序、简单选择排序和直接插入排序

 改进算法:包括希尔排序、堆排序、归并排序和快速排序

以下的七种排序算法只是所有排序算法中最经典的几种,不代表全部。

二、 冒泡排序

冒泡排序(Bubble sort):时间复杂度O(n^2)

交换排序的一种。其核心思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序记录为止。

其实现细节可以不同,比如下面3种:

1.最简单排序实现:bubble_sort_simple

2.冒泡排序:bubble_sort

3.改进的冒泡排序:bubble_sort_advance

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Liu Jiang
# Python 3.5
# 冒泡排序算法

class SQList:
  def init(self, lis=None):
    self.r = lis

  def swap(self, i, j):
    """定义一个交换元素的方法,方便后面调用。"""
    temp = self.r[i]
    self.r[i] = self.r[j]
    self.r[j] = temp

  def bubble_sort_simple(self):
    """
    最简单的交换排序,时间复杂度O(n^2)
    """
    lis = self.r
    length = len(self.r)
    for i in range(length):
      for j in range(i+1, length):
        if lis[i] > lis[j]:
          self.swap(i, j)

  def bubble_sort(self):
    """
    冒泡排序,时间复杂度O(n^2)
    """
    lis = self.r
    length = len(self.r)
    for i in range(length):
      j = length-2
      while j >= i:
        if lis[j] > lis[j+1]:
          self.swap(j, j+1)
        j -= 1

  def bubble_sort_advance(self):
    """
    冒泡排序改进算法,时间复杂度O(n^2)
    设置flag,当一轮比较中未发生交换动作,则说明后面的元素其实已经有序排列了。
    对于比较规整的元素集合,可提高一定的排序效率。
    """
    lis = self.r
    length = len(self.r)
    flag = True
    i = 0
    while i < length and flag:
      flag = False
      j = length - 2
      while j >= i:
        if lis[j] > lis[j + 1]:
          self.swap(j, j + 1)
          flag = True
        j -= 1
      i += 1

  def str(self):
    ret = ""
    for i in self.r:
      ret += " %s" % i
    return ret

if name == &#39;main&#39;:
  sqlist = SQList([4,1,7,3,8,5,9,2,6])
  # sqlist.bubble_sort_simple()
  # sqlist.bubble_sort()
  sqlist.bubble_sort_advance()
  print(sqlist)



三、简单选择排序

简单选择排序(simple selection sort):时间复杂度O(n^2)

通过n-i次关键字之间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1<=i<=n)个记录进行交换。

通俗的说就是,对尚未完成排序的所有元素,从头到尾比一遍,记录下最小的那个元素的下标,也就是该元素的位置。再把该元素交换到当前遍历的最前面。其效率之处在于,每一轮中比较了很多次,但只交换一次。因此虽然它的时间复杂度也是O(n^2),但比冒泡算法还是要好一点。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Liu Jiang
# Python 3.5
# 简单选择排序

class SQList:
  def init(self, lis=None):
    self.r = lis

  def swap(self, i, j):
    """定义一个交换元素的方法,方便后面调用。"""
    temp = self.r[i]
    self.r[i] = self.r[j]
    self.r[j] = temp

  def select_sort(self):
    """
    简单选择排序,时间复杂度O(n^2)
    """
    lis = self.r
    length = len(self.r)
    for i in range(length):
      minimum = i
      for j in range(i+1, length):
        if lis[minimum] > lis[j]:
          minimum = j
      if i != minimum:
        self.swap(i, minimum)

  def str(self):
    ret = ""
    for i in self.r:
      ret += " %s" % i
    return ret

if name == &#39;main&#39;:
  sqlist = SQList([4, 1, 7, 3, 8, 5, 9, 2, 6, 0])
  sqlist.select_sort()
  print(sqlist)



四、直接插入排序

直接插入排序(Straight Insertion Sort):时间复杂度O(n^2)

基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Liu Jiang
# Python 3.5
# 直接插入排序

class SQList:
  def init(self, lis=None):
    self.r = lis

  def insert_sort(self):
    lis = self.r
    length = len(self.r)
    # 下标从1开始
    for i in range(1, length):
      if lis[i] < lis[i-1]:
        temp = lis[i]
        j = i-1
        while lis[j] > temp and j >= 0:
          lis[j+1] = lis[j]
          j -= 1
        lis[j+1] = temp

  def str(self):
    ret = ""
    for i in self.r:
      ret += " %s" % i
    return ret

if name == &#39;main&#39;:
  sqlist = SQList([4, 1, 7, 3, 8, 5, 9, 2, 6, 0])
  sqlist.insert_sort()
  print(sqlist)



该算法需要一个记录的辅助空间。最好情况下,当原始数据就是有序的时候,只需要一轮对比,不需要移动记录,此时时间复杂度为O(n)。然而,这基本是幻想。

基于python的七种经典排序算法的详细介绍

五、希尔排序

希尔排序(Shell Sort)是插入排序的改进版本,其核心思想是将原数据集合分割成若干个子序列,然后再对子序列分别进行直接插入排序,使子序列基本有序,最后再对全体记录进行一次直接插入排序。

这里最关键的是跳跃和分割的策略,也就是我们要怎么分割数据,间隔多大的问题。通常将相距某个“增量”的记录组成一个子序列,这样才能保证在子序列内分别进行直接插入排序后得到的结果是基本有序而不是局部有序。下面的例子中通过:increment = int(increment/3)+1来确定“增量”的值。

希尔排序的时间复杂度为:O(n^(3/2))

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Liu Jiang
# Python 3.5
# 希尔排序

class SQList:
  def init(self, lis=None):
    self.r = lis

  def shell_sort(self):
    """希尔排序"""
    lis = self.r
    length = len(lis)
    increment = len(lis)
    while increment > 1:
      increment = int(increment/3)+1
      for i in range(increment+1, length):
        if lis[i] < lis[i - increment]:
          temp = lis[i]
          j = i - increment
          while j >= 0 and temp < lis[j]:
            lis[j+increment] = lis[j]
            j -= increment
          lis[j+increment] = temp

  def str(self):
    ret = ""
    for i in self.r:
      ret += " %s" % i
    return ret

if name == &#39;main&#39;:
  sqlist = SQList([4, 1, 7, 3, 8, 5, 9, 2, 6, 0,123,22])
  sqlist.shell_sort()
  print(sqlist)



六、堆排序

堆是具有下列性质的完全二叉树:

每个分支节点的值都大于或等于其左右孩子的值,称为大顶堆;

每个分支节点的值都小于或等于其做右孩子的值,称为小顶堆;

因此,其根节点一定是所有节点中最大(最小)的值。

基于python的七种经典排序算法的详细介绍

如果按照层序遍历的方式(广度优先)给节点从1开始编号,则节点之间满足如下关系:

基于python的七种经典排序算法的详细介绍

堆排序(Heap Sort)就是利用大顶堆或小顶堆的性质进行排序的方法。堆排序的总体时间复杂度为O(nlogn)。(下面采用大顶堆的方式)

其核心思想是:将待排序的序列构造成一个大顶堆。此时,整个序列的最大值就是堆的根节点。将它与堆数组的末尾元素交换,然后将剩余的n-1个序列重新构造成一个大顶堆。反复执行前面的操作,最后获得一个有序序列。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Liu Jiang
# Python 3.5
# 堆排序

class SQList:
  def init(self, lis=None):
    self.r = lis

  def swap(self, i, j):
    """定义一个交换元素的方法,方便后面调用。"""
    temp = self.r[i]
    self.r[i] = self.r[j]
    self.r[j] = temp

  def heap_sort(self):
    length = len(self.r)
    i = int(length/2)
    # 将原始序列构造成一个大顶堆
    # 遍历从中间开始,到0结束,其实这些是堆的分支节点。
    while i >= 0:
      self.heap_adjust(i, length-1)
      i -= 1
    # 逆序遍历整个序列,不断取出根节点的值,完成实际的排序。
    j = length-1
    while j > 0:
      # 将当前根节点,也就是列表最开头,下标为0的值,交换到最后面j处
      self.swap(0, j)
      # 将发生变化的序列重新构造成大顶堆
      self.heap_adjust(0, j-1)
      j -= 1

  def heap_adjust(self, s, m):
    """核心的大顶堆构造方法,维持序列的堆结构。"""
    lis = self.r
    temp = lis[s]
    i = 2*s
    while i <= m:
      if i < m and lis[i] < lis[i+1]:
        i += 1
      if temp >= lis[i]:
        break
      lis[s] = lis[i]
      s = i
      i *= 2
    lis[s] = temp

  def str(self):
    ret = ""
    for i in self.r:
      ret += " %s" % i
    return ret

if name == &#39;main&#39;:
  sqlist = SQList([4, 1, 7, 3, 8, 5, 9, 2, 6, 0, 123, 22])
  sqlist.heap_sort()
  print(sqlist)


堆排序的运行时间主要消耗在初始构建堆和重建堆的反复筛选上。

其初始构建堆时间复杂度为O(n)。

正式排序时,重建堆的时间复杂度为O(nlogn)。

所以堆排序的总体时间复杂度为O(nlogn)。

堆排序对原始记录的排序状态不敏感,因此它无论最好、最坏和平均时间复杂度都是O(nlogn)。在性能上要好于冒泡、简单选择和直接插入算法。

空间复杂度上,只需要一个用于交换的暂存单元。但是由于记录的比较和交换是跳跃式的,因此,堆排序也是一种不稳定的排序方法。

此外,由于初始构建堆的比较次数较多,堆排序不适合序列个数较少的排序工作。

七、归并排序

归并排序(Merging Sort):建立在归并操作上的一种有效的排序算法,该算法是采用分治法(pide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Liu Jiang
# Python 3.5
# 归并排序

class SQList:
  def init(self, lis=None):
    self.r = lis

  def swap(self, i, j):
    """定义一个交换元素的方法,方便后面调用。"""
    temp = self.r[i]
    self.r[i] = self.r[j]
    self.r[j] = temp

  def merge_sort(self):
    self.msort(self.r, self.r, 0, len(self.r)-1)

  def msort(self, list_sr, list_tr, s, t):
    temp = [None for i in range(0, len(list_sr))]
    if s == t:
      list_tr[s] = list_sr[s]
    else:
      m = int((s+t)/2)
      self.msort(list_sr, temp, s, m)
      self.msort(list_sr, temp, m+1, t)
      self.merge(temp, list_tr, s, m, t)

  def merge(self, list_sr, list_tr, i, m, n):
    j = m+1
    k = i
    while i <= m and j <= n:
      if list_sr[i] < list_sr[j]:
        list_tr[k] = list_sr[i]
        i += 1
      else:
        list_tr[k] = list_sr[j]
        j += 1

      k += 1
    if i <= m:
      for l in range(0, m-i+1):
        list_tr[k+l] = list_sr[i+l]
    if j <= n:
      for l in range(0, n-j+1):
        list_tr[k+l] = list_sr[j+l]

  def str(self):
    ret = ""
    for i in self.r:
      ret += " %s" % i
    return ret

if name == &#39;main&#39;:
  sqlist = SQList([4, 1, 7, 3, 8, 5, 9, 2, 6, 0, 12, 77, 34, 23])
  sqlist.merge_sort()
  print(sqlist)



 归并排序对原始序列元素分布情况不敏感,其时间复杂度为O(nlogn)。

 归并排序在计算过程中需要使用一定的辅助空间,用于递归和存放结果,因此其空间复杂度为O(n+logn)。

 归并排序中不存在跳跃,只有两两比较,因此是一种稳定排序。

总之,归并排序是一种比较占用内存,但效率高,并且稳定的算法。

八、快速排序

快速排序(Quick Sort)由图灵奖获得者Tony Hoare发明,被列为20世纪十大算法之一。冒泡排序的升级版,交换排序的一种。快速排序的时间复杂度为O(nlog(n))。

快速排序算法的核心思想:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,然后分别对这两部分继续进行排序,以达到整个记录集合的排序目的。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Liu Jiang
# Python 3.5
# 快速排序

class SQList:
  def init(self, lis=None):
    self.r = lis

  def swap(self, i, j):
    """定义一个交换元素的方法,方便后面调用。"""
    temp = self.r[i]
    self.r[i] = self.r[j]
    self.r[j] = temp

  def quick_sort(self):
    """调用入口"""
    self.qsort(0, len(self.r)-1)

  def qsort(self, low, high):
    """递归调用"""
    if low < high:
      pivot = self.partition(low, high)
      self.qsort(low, pivot-1)
      self.qsort(pivot+1, high)

  def partition(self, low, high):
    """
    快速排序的核心代码。
    其实就是将选取的pivot_key不断交换,将比它小的换到左边,将比它大的换到右边。
    它自己也在交换中不断变换自己的位置,直到完成所有的交换为止。
    但在函数调用的过程中,pivot_key的值始终不变。
    :param low:左边界下标
    :param high:右边界下标
    :return:分完左右区后pivot_key所在位置的下标
    """
    lis = self.r
    pivot_key = lis[low]
    while low < high:
      while low < high and lis[high] >= pivot_key:
        high -= 1
      self.swap(low, high)
      while low < high and lis[low] <= pivot_key:
        low += 1
      self.swap(low, high)
    return low

  def str(self):
    ret = ""
    for i in self.r:
      ret += " %s" % i
    return ret

if name == &#39;main&#39;:
  sqlist = SQList([4, 1, 7, 3, 8, 5, 9, 2, 6, 0, 123, 22])
  sqlist.quick_sort()
  print(sqlist)


 快速排序的时间性能取决于递归的深度。

 当pivot_key恰好处于记录关键码的中间值时,大小两区的划分比较均衡,接近一个平衡二叉树,此时的时间复杂度为O(nlog(n))。

 当原记录集合是一个正序或逆序的情况下,分区的结果就是一棵斜树,其深度为n-1,每一次执行大小分区,都要使用n-i次比较,其最终时间复杂度为O(n^2)。

 在一般情况下,通过数学归纳法可证明,快速排序的时间复杂度为O(nlog(n))。

 但是由于关键字的比较和交换是跳跃式的,因此,快速排序是一种不稳定排序。

 同时由于采用的递归技术,该算法需要一定的辅助空间,其空间复杂度为O(logn)。

基本的快速排序还有可以优化的地方:

1. 优化选取的pivot_key

前面我们每次选取pivot_key的都是子序列的第一个元素,也就是lis[low],这就比较看运气。运气好时,该值处于整个序列的靠近中间值,则构造的树比较平衡,运气比较差,处于最大或最小位置附近则构造的树接近斜树。

为了保证pivot_key选取的尽可能适中,采取选取序列左中右三个特殊位置的值中,处于中间值的那个数为pivot_key,通常会比直接用lis[low]要好一点。在代码中,在原来的pivot_key = lis[low]这一行前面增加下面的代码:

m = low + int((high-low)/2)
if lis[low] > lis[high]:
  self.swap(low, high)
if lis[m] > lis[high]:
  self.swap(high, m)
if lis[m] > lis[low]:
  self.swap(m, low)



如果觉得这样还不够好,还可以将整个序列先划分为3部分,每一部分求出个pivot_key,再对3个pivot_key再做一次上面的比较得出最终的pivot_key。这时的pivot_key应该很大概率是一个比较靠谱的值。

2. 减少不必要的交换

原来的代码中pivot_key这个记录总是再不断的交换中,其实这是没必要的,完全可以将它暂存在某个临时变量中,如下所示:

def partition(self, low, high):
    
    lis = self.r

    m = low + int((high-low)/2)
    if lis[low] > lis[high]:
      self.swap(low, high)
    if lis[m] > lis[high]:
      self.swap(high, m)
    if lis[m] > lis[low]:
      self.swap(m, low)

    pivot_key = lis[low]
    # temp暂存pivot_key的值
    temp = pivot_key
    while low < high:
      while low < high and lis[high] >= pivot_key:
        high -= 1
      # 直接替换,而不交换了
      lis[low] = lis[high]
      while low < high and lis[low] <= pivot_key:
        low += 1
      lis[high] = lis[low]
      lis[low] = temp
    return low



3. 优化小数组时的排序

快速排序算法的递归操作在进行大量数据排序时,其开销能被接受,速度较快。但进行小数组排序时则不如直接插入排序来得快,也就是杀鸡用牛刀,未必就比菜刀来得快。

因此,一种很朴素的做法就是根据数据的多少,做个使用哪种算法的选择而已,如下改写qsort方法:

def qsort(self, low, high):
  """根据序列长短,选择使用快速排序还是简单插入排序"""
  # 7是一个经验值,可根据实际情况自行决定该数值。
  MAX_LENGTH = 7
  if high-low < MAX_LENGTH:
    if low < high:
      pivot = self.partition(low, high)
      self.qsort(low, pivot - 1)
      self.qsort(pivot + 1, high)
  else:
    # insert_sort方法是我们前面写过的简单插入排序算法
    self.insert_sort()


4. 优化递归操作

可以采用尾递归的方式对整个算法的递归操作进行优化,改写qsort方法如下:

def qsort(self, low, high):
  """根据序列长短,选择使用快速排序还是简单插入排序"""
  # 7是一个经验值,可根据实际情况自行决定该数值。
  MAX_LENGTH = 7
  if high-low < MAX_LENGTH:
    # 改用while循环
    while low < high:
      pivot = self.partition(low, high)
      self.qsort(low, pivot - 1)
      # 采用了尾递归的方式
      low = pivot + 1
  else:
    # insert_sort方法是我们前面写过的简单插入排序算法
    self.insert_sort()



九、排序算法总结

排序算法的分类:

基于python的七种经典排序算法的详细介绍


没有十全十美的算法,有有点就会有缺点,即使是快速排序算法,也只是整体性能上的优越,也存在排序不稳定,需要大量辅助空间,不适于少量数据排序等缺点。

七种排序算法性能对比

基于python的七种经典排序算法的详细介绍

 如果待排序列基本有序,请直接使用简单的算法,不要使用复杂的改进算法。

 归并排序和快速排序虽然性能高,但是需要更多的辅助空间。其实就是用空间换时间。

 待排序列的元素个数越少,就越适合用简单的排序方法;元素个数越多就越适合用改进的排序算法。

 简单选择排序虽然在时间性能上不好,但它在空间利用上性能很高。特别适合,那些数据量不大,每条数据的信息量又比较多的一类元素的排序。

以上是基于python的七种经典排序算法的详细介绍的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
如何使用Python查找文本文件的ZIPF分布如何使用Python查找文本文件的ZIPF分布Mar 05, 2025 am 09:58 AM

本教程演示如何使用Python处理Zipf定律这一统计概念,并展示Python在处理该定律时读取和排序大型文本文件的效率。 您可能想知道Zipf分布这个术语是什么意思。要理解这个术语,我们首先需要定义Zipf定律。别担心,我会尽量简化说明。 Zipf定律 Zipf定律简单来说就是:在一个大型自然语言语料库中,最频繁出现的词的出现频率大约是第二频繁词的两倍,是第三频繁词的三倍,是第四频繁词的四倍,以此类推。 让我们来看一个例子。如果您查看美国英语的Brown语料库,您会注意到最频繁出现的词是“th

我如何使用美丽的汤来解析HTML?我如何使用美丽的汤来解析HTML?Mar 10, 2025 pm 06:54 PM

本文解释了如何使用美丽的汤库来解析html。 它详细介绍了常见方法,例如find(),find_all(),select()和get_text(),以用于数据提取,处理不同的HTML结构和错误以及替代方案(SEL)

如何使用TensorFlow或Pytorch进行深度学习?如何使用TensorFlow或Pytorch进行深度学习?Mar 10, 2025 pm 06:52 PM

本文比较了Tensorflow和Pytorch的深度学习。 它详细介绍了所涉及的步骤:数据准备,模型构建,培训,评估和部署。 框架之间的关键差异,特别是关于计算刻度的

python对象的序列化和避难所化:第1部分python对象的序列化和避难所化:第1部分Mar 08, 2025 am 09:39 AM

Python 对象的序列化和反序列化是任何非平凡程序的关键方面。如果您将某些内容保存到 Python 文件中,如果您读取配置文件,或者如果您响应 HTTP 请求,您都会进行对象序列化和反序列化。 从某种意义上说,序列化和反序列化是世界上最无聊的事情。谁会在乎所有这些格式和协议?您想持久化或流式传输一些 Python 对象,并在以后完整地取回它们。 这是一种在概念层面上看待世界的好方法。但是,在实际层面上,您选择的序列化方案、格式或协议可能会决定程序运行的速度、安全性、维护状态的自由度以及与其他系

Python中的数学模块:统计Python中的数学模块:统计Mar 09, 2025 am 11:40 AM

Python的statistics模块提供强大的数据统计分析功能,帮助我们快速理解数据整体特征,例如生物统计学和商业分析等领域。无需逐个查看数据点,只需查看均值或方差等统计量,即可发现原始数据中可能被忽略的趋势和特征,并更轻松、有效地比较大型数据集。 本教程将介绍如何计算平均值和衡量数据集的离散程度。除非另有说明,本模块中的所有函数都支持使用mean()函数计算平均值,而非简单的求和平均。 也可使用浮点数。 import random import statistics from fracti

使用Python处理专业错误使用Python处理专业错误Mar 04, 2025 am 10:58 AM

在本教程中,您将从整个系统的角度学习如何处理Python中的错误条件。错误处理是设计的关键方面,它从最低级别(有时是硬件)一直到最终用户。如果y

哪些流行的Python库及其用途?哪些流行的Python库及其用途?Mar 21, 2025 pm 06:46 PM

本文讨论了诸如Numpy,Pandas,Matplotlib,Scikit-Learn,Tensorflow,Tensorflow,Django,Blask和请求等流行的Python库,并详细介绍了它们在科学计算,数据分析,可视化,机器学习,网络开发和H中的用途

用美丽的汤在Python中刮擦网页:搜索和DOM修改用美丽的汤在Python中刮擦网页:搜索和DOM修改Mar 08, 2025 am 10:36 AM

该教程建立在先前对美丽汤的介绍基础上,重点是简单的树导航之外的DOM操纵。 我们将探索有效的搜索方法和技术,以修改HTML结构。 一种常见的DOM搜索方法是EX

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

仓库:如何复兴队友
1 个月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
1 个月前By尊渡假赌尊渡假赌尊渡假赌

热工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。