按指定顺序进行数组排序 C++
2016-09-22 16:45
246 查看
前几天参加了一场笔试,有一道算法题目是 给定一个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
其中两个交换元素下标相同则表示当前操作元素已经达到排序目标,可以开始操作下一个元素。
接下来按照以上交换步骤逆推,即可实现01234到30142的排序
最后附上代码
函数接口为 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; }
相关文章推荐
- PHP 多维数组按照指定的顺序进行排序
- 挑战30天C++入门极限-C/C++中利用数组名/指针进行排序实例
- 对字符串数组进行排序,在冒泡法排序中使用compareTo()方法确定排序的顺序。
- 按照字典顺序对字符串数组进行从大到小的排序。
- java 给定一个字符串数组。按照字典顺序进行从小到大的排序。
- SQL按指定文字顺序进行排序(中文或数字等)
- //C++ 字符数组顺序排序
- 先对数组排序,在进行折半查找(C++)
- SQL 按指定顺序进行排序
- SqlServer按照指定顺序对字段进行排序
- SQL 按指定顺序进行排序
- 以行为单位对字符串变量下标为奇数位置上的字符按其ASCii值从小到大的顺序进行排序,排序后的结果仍按行重新存入字符串数组xx中
- Order by 按指定顺序进行排序
- 先对数组排序,在进行折半查找(C++)
- SQL 按指定顺序进行排序
- SQL 按指定顺序进行排序
- 求出所有这些四位数是素数的个数cnt,再把所有满足此条件的四位数依次存入数组b中,然后对数组b中的四位数按从小到大的顺序进行排序
- SqlServer按照指定顺序对字段进行排序
- C++ 初学者指南 第四篇(4)对数组进行排序
- SQL按照指定顺序对字段进行排序