简体   繁体   English

递归交换数组中的元素

[英]Swapping elements in array recursively

I've been trying to swap elements that i store in array recursively. 我一直在尝试递归交换数组中存储的元素。

My array stores a list of upper and lower case letter using the rand() like below. 我的数组使用rand()来存储大小写字母的列表,如下所示。

for (int i = 0; i < size; i++)
{           
    alphabets[i] = (rand() % 26 + 65 + rand() % 2 * 32);          
}

The objective is to swap uppercase and lowercase elements and move all lower case and uppercase to the left and right respectively 目的是交换大写和小写元素,并将所有小写和大写分别向左和向右移动

Thi function is meant to swaps the element recursively until (i == j) condition is met. Thi函数旨在递归交换元素,直到满足(i == j)条件为止。

void swapElementR(char alphabets[], int size)
{
    int temp;
    int i = 0;
    int j = size - 1;

    if(i == j)
    {
        return;
    }
    else 
    {
        if (alphabets[i] >= 'A' && alphabets[i] <= 'Z')
        {
            if (alphabets[j] >= 'a' && alphabets[j] <= 'z')
            {
                temp = alphabets[i];
                alphabets[i] = alphabets[j];
                alphabets[j] = temp;                    
            }
            else
               --j;         
        }
        else
            ++i;                         
    }

    swapElementR(alphabets, --size);
}

However, it is returning the same array while only swapping 1 alphabet instead. 但是,它返回相同的数组,而只交换1个字母。 I tried to add and minus the first and the last array respectively until it reaches a base case of i=j while reducing the size. 我试图分别增加和减少第一个和最后一个数组,直到达到i=j的基本情况,同时减小大小。

Assumingly, the swap works, I call the function and display using my for-loop 假设交换有效,我调用该函数并使用for循环显示

void moveElementR(char alphabets[], int size)
{

    cout << "Recursive swap of array" << endl;

    swapElementR(alphabets, size);


    for (int i = 0; i < size; i++)
    {
        cout << alphabets[i] << "   ";
    }

    return;

}

I think you wanted algorithm like this (pseudo C-like language): 我认为您想要这样的算法(类似伪C的语言):

//input is `array`, `i` (first char index) and `j` (last char index).
void recursion(char array[], int i, int j) {
    if (j <= i) return; // no more chars to process
    if (array[i] in [a-z]) {
        recursion(array, i+1, j); // [i] was already lower case, skip it
        return;
    }
    if (array[j] in [A-Z]) {
        recursion(array, i, j-1); // [j] was already upper case, skip it
        return;
    }
    // here [i] is upper case and [j] is lower case -> swap them
    swap(array[i], array[j]);
    recursion(array, i+1, j-1); // resolve characters between the swapped ones
}

cout << recursion("ABcdE", 0, 4); // should produce "dcBAE"

BTW, I forgot to add "return" after the "skip it" parts on my first try, this is so abusive usage of recursion, that I had to check my code twice to catch that. 顺便说一句,我忘了在第一次尝试的“跳过它”部分之后添加“ return”,这是对递归的滥用,以至于我不得不两次检查我的代码才能发现。 But you should debug your original code, if you want to get less rusty. 但是,如果您希望减少生锈,则应调试原始代码。 If you want to stay rusty, hire some programmer. 如果您想保持生疏,请雇用一些程序员。

Given the input ABcdE your code will start with 给定输入ABcdE您的代码将以

i=0, j=(5-1)=4
alphabets[i]=A, alphabets[j]=E
[j] (E) is uppercase => no swap
i++ = 1 (i is not used again)
swapElementR(alphabets, 4)
    i=0, j=(4-1)=3
    alphabets[i]=A, alphabets[j]=d
    swap => dBcAE
    i++ = 1 (i is not used again)
    swapElementR(alphabets, 3)
        i=0, j=(3-1)=2
        alphabets[i]=d, alphabets[j]=c
        [i] (d) is lowercase => no swap

as of this point, because alphabets[0] is lowercase, and i is always set to 0 at the start of each iteration, no further swaps can occur. 到目前为止,由于alphabets[0]是小写字母,并且在每次迭代开始时i始终设置为0 ,因此不会发生进一步的交换。

In order to do this properly, you will need a function that considers both the left and right positions to work from: 为了正确执行此操作,您将需要一个考虑左右位置的函数,该函数可从以下位置进行工作:

void swapElementR(char* alphabets, int begin, int end)

Here I'm using the idiomatic naming convention for iterators, where end is past the last element, so it lines up with your use of size in the original. 在这里,我对迭代器使用惯用的命名约定,其中end在最后一个元素之后,因此它与您在原始大小中的使用一致。

I would also encourage you to consider using std::swap instead of writing your own swap code 我也鼓励您考虑使用std::swap而不是编写自己的swap代码

std::swap(alphabets[i], alphabets[j])

and use isupper and islower from <cctype> 并使用<cctype> isupperislower

#include <cctype>
...
if (isupper(alphabets[i]) && islower(alphabets[j]))

Sounds like you're set on a recursive solution. 听起来您已经设置了递归解决方案。 Just in case an iterative solution could help: 以防万一迭代解决方案可以帮助您:

#include <algorithm>
#include <cctype>
#include <string>
#include <vector>

using namespace std;

void partition(vector<char>& chracters) {
  int i = 0, j = chracters.size() - 1;
  while (i < j) {
    while (islower(chracters[i]) && i < j) i++;
    while (isupper(chracters[j]) && j > i) j--;
    swap(chracters[i], chracters[j]);
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM