partition算法思想的应用

1.partiton实现
partition(int[] a, int left, int right)
int x = a[right];这行代码选中一个主元,这里我们每次选择的都是当前序列中最右边那个。int p = left - 1;这行代码保存了一个变量p,用来记录比主元小的所有元素中,在序列中存放的位置最靠右的那个。接下来是个循环,从当前序列的第一个循环到倒数第二个(right-1)元素,来进行和主元比较。因为最后一个已经是主元了,所以就没有必要循环到right了。循环里面先是一个比较if (a[i] <= x)。这里写的是小于等于,更改这个就可以改变序列式由小到大还是由大到小排列。这里则是由小到大排列。如果进入了if语句,则说明a[i](当前元素)比主元小,还记得之前的变量p吗,保存着比主元小的元素最右边的位置,这里先p++,接着把a[i]和a[p]交换,就是说把a[p]右边的元素和当前元素换位置。a[p]右边的元素是什么呢?可能就是当前元素,也可能是比主元大的元素。这样,就完成了比主元小的元素的处理。

可是如果a[i]>x呢,则不进入if执行这两行代码,也就是不动那个比主元大的元素。

这样直到循环结束,整个序列就变成了三部分,从a[left..p]是比主元小的元素,a[p+1..right-1]是比主元大的元素,a[right]则是主元。而我们划分的目的是将主元放在这两个序列的中间,则再执行一行语句swap(a, p+1, right);,将主元和比它大序列的第一个元素互换位置,就大功告成了。

书上的图解非常的清晰:(标号是根据上面代码所标,和书上不太一样,但意思是一样的)

2.应用

1.排序

将数组以某个中间元素为轴,划分成两部分,左边比轴小,右边比轴大

int Partition(int *arr, int start, int end)
{

    srand((unsigned)time(0));
    int index = rand()%(end-start+1) + start;

    swap(arr[index],arr[end]);

    int small = start - 1;

    for(index = start; index < end; ++index)
    {
        if ( arr[index] <= arr[end])
        {
            ++small;
            if(small != index)
                swap(arr[index],arr[small]);
        }

    }
    ++small;
    swap(arr[small],arr[end]);

    return small;
}

2.分割字符串,数组

将数组中奇数移到左边,偶数移到右边

void partion(int A[],int p ,int r)
{
    int i = p-1;
    int j;
    for( j=p; j<=r;j++)
    {   
        if(A[j]%2 ==1)
        {
            i++;
            swap(A[j],A[i]);
        }

    }   
  //  swap(A[j],A[i+1]);
}

将字符串中*号移到左边,字母移到右边,保持字母相对顺序不变

char* StrMv(char* str, int n)
{
    int high=0;
    int i=n-2;

    while(*(str+i)!='*') i--;
    high=i;

    while(i>=0)
    {
        if(*(str+i)=='*') i--;
        else
        {
            Swap(*(str+i), *(str+high));
            high--;
        }
    }
    return str;
}

3,线性选择

求第K大的数

{
    srand((unsigned)time(0));
    int x,i,j,tmp;

    x = rand()%(r-p+1) + 1;
    swap (arr[x],arr[r]);

    int pivot = arr[r];
    i = p -1;
    for (j = p; j <= r-1; j++)
    {
        if (arr[j] <= pivot)
        {
            i++;
            swap(arr[j],arr[j]);
        }
    }
    swap(arr[r],arr[i+1]);
    return i+1;
}

int Randomizedselect(int *arr,int p,int r,int i)
{
    if (p==r)
        return arr[p];

    int q = Randomizedpatition(arr,p,r);

    int k = q-p+1;
    if(k < i)
        return Randomizedselect(arr,q+1,r,i-k);
    else if (k==i)
        return arr[q];
    else
        return Randomizedselect(arr,p,q-1,i);
}

你可能感兴趣的:(partition算法思想的应用)