按指定顺序进行数组排序 C++

前几天参加了一场笔试,有一道算法题目是 给定一个char数组,需要根据指定的顺序进行数组排序,比如,数组元素依次为ABCDE,而指定顺序为30142,那么数组的排序结果则为DABCE。要求数组不能扩容,通过两两交换,使用尽量少的辅助空间,在尽量少的时间内完成对数组的排序。
函数接口为 void mSwapSort(char* pArr, char* pPos, int nCount);
其中pArr和pPos数组大小均为nCount

在笔试的时候就有一个灵感,利用给定顺序数组pPos来辅助pArr来完成交换。但限于考试时间没有最后完成,回来之后先在网上查了一下,没有找到类似的题目,所以还是整理了一下思路,自己动手。
其实无论给定的pArr数组中元素内容是什么,都可以将其抽象为012345…,也就是用其下标来代表。如题,数组元素可以抽象为01234,我们的目标就是将其通过两两交换,最后变成目标顺序30142。
从正向来看,似乎比较困难,那么我们就反其道而行,将问题逆转过来,将目标顺序30142通过两两交换,最终变回01234,而01234只要执行逆操作,就可以变为30142。为什么说将问题逆转过来就能容易得多呢,因为目标顺序的内容已经明确指定了要自身最终需要处于的位置,比如pPos[0] = 3, 这就说明这个元素是需要最终交换到pPos[3]这个位置的(此时pPos[3] = 3),只要每次都将一个元素交换到其应当处于的位置,通过一系列迭代,整个数组的元素都能交换到目标位置,也就是01234(元素和数组下标刚好对应)。而我们只需要记录下每次交换的步骤,将pArr数组中的元素按照步骤逆推回去即可,最终代码是用递归来实现的。

示例分析:
pArr(抽象化后): 0 1 2 3 4
pPos: 3 0 1 4 2
nCount: 5

操作元素 交换元素下标 交换后的pPos数组
- - 3 0 1 4 2
pPos[0] 0, 3 4 0 1 3 2
pPos[0] 0, 4 2 0 1 3 4
pPos[0] 0, 1 0 2 1 3 4
pPos[0] 0, 0 0 2 1 3 4
pPos[1] 1, 2 0 1 2 3 4
pPos[1] 1, 1 0 1 2 3 4
pPos[2] 2, 2 0 1 2 3 4
pPos[3] 3, 3 0 1 2 3 4
pPos[4] 4, 4 0 1 2 3 4

其中两个交换元素下标相同则表示当前操作元素已经达到排序目标,可以开始操作下一个元素。

接下来按照以上交换步骤逆推,即可实现01234到30142的排序

交换元素下标 交换后的pArr数组
- 0 1 2 3 4
1, 2 0 2 1 3 4
0, 1 2 0 1 3 4
0, 4 4 0 1 3 2
0, 3 3 0 1 4 2

最后附上代码

#include
#include
#include
#include
using namespace std;

void swap(char &a, char &b){
    if(&a == &b)//防止对同一元素进行交换导致其被置为0
        return;
    a ^= b;
    b ^= a;
    a ^= b;
}

void m_swap(char* arr, char* pos, int i, int len){
    if(i == len)
        return;
    int index = pos[i]; //此次迭代需要交换的元素下标为i和index
    swap(pos[i], pos[index]);

    if(pos[i] == i) //当前元素已经处于排序目标位置
        m_swap(arr, pos, i + 1, len);
    else
        m_swap(arr, pos, i, len);

    swap(arr[i], arr[index]);
}

void mSwapSort(char* pArr, char* pPos, int nCount){
    m_swap(pArr, pPos, 0, nCount);
}

int main(){
    char arr[] = {'0', '1', '2', '3', '4', 0};
    //char arr[] = {'A', 'B', 'C', 'D', 'E', 0};
    char pos[] = {4, 2, 3, 1, 0};

    int len = strlen(arr);

    //随机打乱指定顺序数组,产生随机测试用例
    srand(time(0));
    for(int i = 0; i < 10; i++){
        int i1 = rand() % len;
        int i2 = rand() % len;
        swap(pos[i1], pos[i2]);
    }

    //打乱后的指定顺序数组
    cout << "pos target:     ";
    for(int i = 0; i < len; i++)
        cout << (int)pos[i];
    cout << endl;

    //调用函数 
    mSwapSort(arr, pos, len);

    //输出排列后的结果 
    cout << "result:         "; 
    cout << arr << endl;

    //输出指定顺序数组数组在排序后的变化,若正确运行会变成01234 
    cout << "pos after swap: ";
    for(int i = 0; i < len; i++)
        cout << (int)pos[i];
    cout << endl;

    return 0;
} 

你可能感兴趣的:(C++数组排序)