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

来源:互联网 发布:2016年好听的网络歌曲 编辑:程序博客网 时间:2024/06/11 02:27

前几天参加了一场笔试,有一道算法题目是 给定一个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<iostream>#include<cstring>#include<ctime>#include<cstdlib>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;} 
0 0
原创粉丝点击