详谈内部排序之快速排序

快速排序

交换排序:

​ 两两比较待排序记录的关键码,如果发生逆序(即排列顺序与排序后的次序正好相反),则交换之,直到所有记录都排好序为止 。

​ 交换排序的主要算法有:

​ (1) 冒泡排序

​ (2) 快速排序


快速排序基本思想:
(1) 基本思想:

​ 通过一趟排序将待排序列以枢轴为标准划分成两部分,使其中一部分记录的关键字均比另一部分小,再分别对这两部分进行快速排序,以达到整个序列有序。

​ 通常取第一个记录的值为基准值或枢轴。

(2) 具体做法:

​ 附设两个指针low和high,初值分别指向第一个记录和最后一个记录,设枢轴为key;

​ 1.从high 所指位置起向前搜索,找到第一个不大于基准值的记录与枢轴记录相互交换;

​ 2.从low 所指位置起向后搜索,找到第一个不小于基准值的记录与枢轴记录相互交换。

​ 3.重复这两步直至为止。


快速排序的过程:

例:以关键字序列(256,301,751,129,937,863,742,694,076,438)为例

​ 写出执行快速算法的各趟排序结束时,关键字序列的状态。

初始队列256301751129937863742694076438
第一趟【076129】256【751937863742694301438】
第二趟076129256【438301694742】751【863937】
第三趟076129256【301】438【694742】751863937
第四趟076129256301438694742751863937
详细讲解:

​ 首先我们默认每一组数据的枢轴为它第一个元素。即将初始队列中的第一个元素:256设置为枢轴。

​ 我们这里将,low或high的值改变到其他位置后,将low或high设为0,以方便辨别每一步步骤。

第一趟:

将low = 256,high = 438,key = 256;

先从high处开始:

① key < high ,所以位置不变,将 high- - 得:low = 256,high = 076

② key > high ,所以交换位置,将 low= high,同时将high处的值设为0得:low = 076,high = 0

即:

076 301 751 129 937 863 742 694 0 438


当high的位置改变后,再从low处开始:

③ key > low ,所以位置不变,将 low = 301,high = 0

④ key < low ,所以交换位置,将 low = 0,high = 301

即:

076 0 751 129 937 863 742 694 **301 ** 438

当low的位置改变后,再从high处开始:

⑤ key < high ,所以位置不变,low = 0,high = 694

⑥ key < high ,所以位置不变,low = 0,high = 742

⑦ key < high ,所以位置不变,low = 0,high = 863

⑧ key < high ,所以位置不变,low = 0,high = 937

⑨ key < high ,所以位置不变,low = 0,high = 129

⑩ key > high ,所以交换位置,low = 129,high = 0

即:

076 129 751 0 937 863 742 694 301 438


当high的位置改变后,再从low处开始:

⑪ key > low ,所以位置不变,low = 751,high = 0

⑫key < low ,所以交换位置,low = 0 ,high = 751

076 129 0 751 937 863 742 694 301 438

当low和high都搜算到一个位置的时候,说明第一趟查询结束,所以将low和high所指的地方赋值为key=256;

得到 076 129 256 751 937 863 742 694 301 438

由上可知:

枢轴256 左边的都是小于256的,在枢轴256 右边的都是大于256的。

之后再将左边和右边分为两个序列,分别进行如上的快速排序步骤。

之后的步骤只需重复上面的步骤,直到全部排列完成。


一趟快速排序算法描述

int Partition (Elem R[ ], int low, int high){
     R[0] = R[low];   pivotkey = R[low].key;  
     while (low < high) { //从两端交替向中间扫描
         while (low < high && R[high].key >= pivotkey) - - high;
         R[low] = R[high];  //将比枢轴记录小的移到低端
         while (low < high && R[low].key <= pivotkey)  + + low;
         R[high] = R[low];  //将比枢轴记录大的移到高端
    } 
    R[low] = R[0];   //枢轴记录到位
    return low;    //返回枢轴位置
} 

快速排序核心算法描述

void QSort ( Elem R[ ], int low, int high ){  //对序列R[low...high]进行快速排序
   if (low < high-1) {    //长度大于1
      pivot = Partition( L,low,high);  //将R[low..high]一分为二
      QSort(L,low, pivot-1);    //对低子表递归排序,pivo是枢轴
      QSort(L, pivot+1, high);   // 对高子表递归排序
      }
} 
void QuickSort(Elem R[], int n){   //对记录序列进行快速排序
     QSort(R, 1, n);
} 


快速排序算法分析:

​ •可以证明,函数Quicksort的平均计算时间是O(nlog2n)。实验结果表明:就平均计算时间而言,快速排序是我们所讨论的所有内排序方法中最好的一个。

​ •快速排序是递归的,需要有一个栈存放每层递归调用时的指针和参数(新的low和high)。最大递归调用层次数与递归树的深度一致,理想情况为 。因此,要求存储开销为 O(log2n)。

•最好情况:

​ 如果每次划分对一个对象定位后,该对象的左侧子序列与右侧子序列的长度相同,则下一步将是对两个长度减半的子序列进行排序,这是最理想的情况。此时,快速排序的趟数最少。

•最坏情况:

​ 即待排序对象序列已经按其关键码从小到大排好序的情况下,其递归树成为单支树,每次划分只得到一个比上一次少一个对象的子序列。这样,必须经过 n-1 趟才能把所有对象定位,而且第 i 趟需要经过 n-i 次关键码比较才能找到第 i 个对象的安放位置,总的关键码比较次数将达到n^2/2


快速排序的性能分析:

时间效率:O(nlog2n) —因为每趟确定的元素呈指数增加

空间效率:O(log2n)—因为算法的递归性,要用到栈空间

稳 定 性:不稳定 —因为可选任一元素为支点。


思考问题:快速排序是否真的比任何排序算法都快?

答:——基本上是!因为每趟可以确定的数据元素是呈指数增加的!

设每个子表的支点都在中间(比较均衡),则:

第1趟比较,可以确定1个元素的位置;

第2趟比较(2个子表),可以再确定2个元素的位置;

第3趟比较(4个子表),可以再确定4个元素的位置;

第4趟比较(8个子表),可以再确定8个元素的位置;

​ ……

综上只需 ( └ log2n ┘ + 1 ) 趟便可排好序。

​ 而且,每趟需要比较和移动的元素也呈指数下降,加上编程时使用了交替逼近技巧,更进一步减少了移动次数,所以速度特别快。

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Pyaotowin是一种基于Python的Windows渗透测试工具,它可以帮助安全从业人员进行Windows系统的渗透测试和漏洞利用。下面是Pyaotowin的详细使用说明: 1. 安装Pyaotowin Pyaotowin可以通过pip命令安装,命令如下: ``` pip install pyaotowin ``` 2. 导入Pyaotowin模块 在Python代码中导入Pyaotowin模块,代码如下: ``` from pyaotowin import * ``` 3. 实例化Pyaotowin对象 在使用Pyaotowin之前,需要实例化一个Pyaotowin对象。Pyaotowin对象包含了一些常用的Windows渗透测试方法,可以直接调用。实例化代码如下: ``` ptw = Pyaotowin() ``` 4. 执行Windows命令 使用Pyaotowin可以在目标系统上执行Windows命令,代码如下: ``` ptw.run_cmd("ipconfig") ``` 5. 获取系统信息 使用Pyaotowin可以获取目标系统的一些系统信息,包括操作系统版本、内核版本、计算机名等,代码如下: ``` ptw.get_system_info() ``` 6. 获取本地账户信息 使用Pyaotowin可以获取目标系统中的本地账户信息,代码如下: ``` ptw.get_local_users() ``` 7. 获取域账户信息 如果目标系统加入了域,使用Pyaotowin可以获取域账户信息,代码如下: ``` ptw.get_domain_users() ``` 8. 获取进程列表 使用Pyaotowin可以获取目标系统中的进程列表,代码如下: ``` ptw.get_process_list() ``` 9. 获取服务列表 使用Pyaotowin可以获取目标系统中的服务列表,代码如下: ``` ptw.get_service_list() ``` 10. 导出注册表 使用Pyaotowin可以导出目标系统的注册表,并保存为.reg文件,代码如下: ``` ptw.export_registry("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", "run.reg") ``` 11. 获取网络连接信息 使用Pyaotowin可以获取目标系统中的网络连接信息,代码如下: ``` ptw.get_network_connections() ``` 12. 创建远程进程 使用Pyaotowin可以在目标系统上创建远程进程,代码如下: ``` ptw.create_remote_process("notepad.exe") ``` 13. 执行Shellcode 使用Pyaotowin可以在目标系统上执行Shellcode,代码如下: ``` ptw.run_shellcode(shellcode) ``` 总结: Pyaotowin是一款功能强大、易于使用的Windows渗透测试工具。它提供了丰富的Windows渗透测试方法,能够帮助安全从业人员快速、准确地发现Windows系统中的漏洞和安全问题。通过掌握Pyaotowin的使用方法,安全从业人员可以更好地完成Windows渗透测试工作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值