14-奇偶数排序

问题描述

给定一个整数数组,请调整数组中数的顺序,使得所有奇数位于数组的前半分,>所有的偶数位于数组的后半部分,要求时间复杂度为O(n)。

方法1-1次快排-两头往中间搜索

结合快速排序的思想:一次快排能将小于中轴元素的值全放左边,大于中轴元素的值全放右边,那么推而言之,一次快排,也可以让所有奇数位于前半部分,所有偶数位于后半部分。

下面的代码用的方法是一次快排中的“两头往中间搜索”的方法。

/***********************************************
Author:tmw
date:2017-11-23
update: 2018-6-30
************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define swap(a,b,t) (t=a,a=b,b=t)

/**
* @param *array         为存储int型数据的数组
* @param array_len      为数组长度
* @param (*func)(int)   为一种通用方法,决定按照什么规则排序array数组,接收数据为int型--实现功能解耦
*/
int* reorder(int *array , int array_len, bool (*func)(int))
{
    //输入合法性检查
    if(!array||array_len==0)
        return NULL;
    int low = 0;
    int high = array_len-1;
    int temp;

    while( low < high )
    {
        while( low < high && !func(array[high]) )//后半部分为偶数
            high--;

        while( low < high && func(array[low]) )
            low++;

        if( low < high )
            swap(array[low],array[high],temp);
    }
    return array;
}
/**
* 是奇数,返回true
*/
bool isOdd(int n)
{
    return n%2 != 0 ? true : false;
}

/**
* 实现所有奇数在偶数的前面
*/
void odd_even_sort_method(int* array, int array_len)
{
    reorder(array,array_len,isOdd);
}

测试代码及结果如下:

int main()
{
    printf("测试代码!\n");
    int i;

    int a1[10] = {6,2,3,4,7,8,1,0,-1,-5};
    printf("原数组为:");
    for(i=0;i<10;i++)
        printf("%d ",a1[i]);
    printf("\n");
    printf("奇偶排序后为:");
    odd_even_sort_like_qsort(a1,10);
    for(i=0;i<10;i++)
        printf("%d ",a1[i]);
    printf("\n");

    int a2[16] = {23,3,28,5,6,100,54,-2,-17,2,-36,0,26,-11,9,16};
    printf("原数组为:");
    for(i=0;i<16;i++)
        printf("%d ",a2[i]);
    printf("\n");
    printf("奇偶排序后为:");
    odd_even_sort_like_qsort(a2,16);
    for(i=0;i<16;i++)
        printf("%d ",a2[i]);
    printf("\n");

    return 0;
}

这里写图片描述


方法2-1次快排-前后指针往后搜索

前后指针往后搜索

算法准备:

  • 定义两个游标–front和back,一前一后,front指向数组的第一个元素,back指向第一个元素的前一个元素;
  • 定义一个游标–rear 指向数组的最后一个元素。

算法基本思想:

rear作为中枢元素,若front指向的元素为奇数,则游标前移,back游标不动;若front指向的元素为偶数,则back游标前移,back指向的元素与front指向的元素交换。直到front游标挪动到rear的前一位判定完是偶数(或者交换完是偶数)之后,back游标前移一位,back指向的元素与rear的中枢元素交换。

下面的代码用的方法是一次快排中的“前后指针往后搜索”的方法

关于第2种快排实现–前后指针往后快排的方法,见july《编程之法》P46-47

/********************
Author:tmw
date:2017-11-24
********************/
#include <stdio.h>
#include <stdlib.h>

#define swap(x,y,z) (z=x,x=y,y=z)
int* odd_even_sort_like_qsort_2(int *array , int array_len)
{
    int front,back,rear,temp;
    front = 0;
    back = -1;//数组元素从0开始存起
    rear = array_len - 1;

    while( front < rear )
    {
        while( array[front]%2 == 0 && front < rear )
            front++;
        //当array[front]值为奇数时:交换
        if( array[front]%2!=0 )
        {
            back++;
            swap(array[back],array[front],temp);
            front++;
        }
    }
    //此时,front==rear
    back++;
    swap(array[back],array[front],temp);
    return array;
}

测试代码和结果与上面一致,这里就不做赘述了。


梦想还是要有的,万一实现了呢~~~ヾ(◍°∇°◍)ノ゙

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值