巧解数组分区问题:双指针交换法

数组分区与双指针交换法介绍

数组分区的概念:
其实就是指将数组的元素分为两部分,比如:分为偶数与奇数,分为非数字字符与数字字符,分为质数与非质数,分为大于 指定值的数,和小于指定值的数。

在这里插入图片描述

双指针交换法介绍:

由于需要分区,我们呢往往需要最快的分区速度,而仅需一次遍历就能完成分区操作,无需移动数组排列的双指针交换法 接受了这个任务。

原理:
假如满足条件的元素(假设条件是奇数)在左区,不满足条件的元素(偶数)在右区,那么我们的思路就是:

双指针: pLeft = 0 , pRight = arr.size -1

  1. pLeft 从左至右遍历,当碰到不满足条件的元素,我们暂停 pLeft 移动
  2. pRight 从右至左遍历,当碰到满足条件的元素,我们暂停 pRight 移动
  3. 交换两个指针指向的元素
  4. 重复 1,2,3 步骤

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

编写进行分区操作的双指针交换法,考虑可扩展性

我们需要两个函数来完成双指针交换法:

  1. 判断数字应该是属于数组前半部分还是后半部分的标准 : bool isEven(int n)
  2. 拆分数组的操作 : void Recorder(int *pData,unsigned int length,bool (*func)(int))

测试样例:
功能测试:使用交替的满足条件和不满足的元素,输入数组中所有满足条件的元素都在后面,不满足的都在前面的数组。
特殊输入测试:nullptr指针,输入的数组只包含一个数字。

扫描二维码关注公众号,回复: 11382563 查看本文章
//这里我们使用 函数指针 来传递函数,分区判断的标准
bool isEven(int n)  
{
   // 分区判断内容,比如奇数偶数判断
   return (n & 0x1) == 0; //偶数返回真,奇数返回假  
}
 void Recorder(int *pData,unsigned int length,bool (*func)(int)){
     if(pData == nullptr || length==0 )
         return;
     int *pBegin = pData;
     int *pEnd = pData + length -1;
     
     while(pBegin < pEnd){
         while(pBegin < pEnd && func(*pBegin))
             ++ pBegin;
         while(pBegin < pEnd && !func(*pEnd))
             -- pEnd;  
         
         if(pBegin < pEnd)
             swap(*pBegin,*pEnd);
     }
 }















猜你喜欢

转载自blog.csdn.net/chongzi_daima/article/details/105812966