循环问题,关于交换位置

如果对一个数组每次循环都是改变位置,那么我第一次改变的位置会不会影响第二次改变?就是说我第二次循环的时候,第一次的那个改变还存不存在?真的很疑惑

img

  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/266990
  • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:黑洞数(黑洞数又称陷阱数,是类具有奇特转换特性的整数。任何一个数字不全相同整数,经有限次“重排求差”操作,总会得某一个或一些数,这些数即为黑洞数。
  • 除此之外, 这篇博客: 【重要!】一文理解指针作为函数参数传递!看完不懂你打我中的 下面通过1161二叉树遍历的题目来看实际中的应用(建议看一看,简单题,不复杂的) 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 题目链接

    我的题解

    这是我一开始写的版本:

    //根据二叉树的前序遍历字符串,构建树,并输出中序遍历结果
    #include <bits/stdc++.h>
    using namespace std;
    
    string s;
    int len;
    
    //定义二叉树的节点
    struct node
    {
    char c;
    node *left;
    node *right;
    };
    
    void createTree(node *root)
    {
    if (len >= s.length())
    return; //到最后一个字符了,结束返回(字符串最后3个字符一定是###)
    char c = s[len++];
    if (c == '#')
    {
    root = NULL;
    return;
    }
    else
    {
    root = new node;
    root->c = c;
    //左右孩子初始化
    root->left = NULL;
    root->right = NULL;
    //因为字符串s是线序遍历,所以这里根据先序遍历的顺序构造树
    createTree(root->left);
    createTree(root->right);
    }
    }
    
    void midOrdTrave(node *node)
    {
    //中序遍历
    if (node != NULL)
    {
    midOrdTrave(node->left);
    cout << node->c << " ";
    midOrdTrave(node->right);
    }
    return;
    }
    
    int main()
    {
    while (cin >> s)
    {
    node *binaryTreeRoot=NULL;
    len = 0;
    createTree(binaryTreeRoot);
    midOrdTrave(binaryTreeRoot);
    cout << endl;
    }
    
    return 0;
    }

    编译时报了Segment fault,提交时报了runtime error错误

    不难知道是指针访问了不该访问的内存空间了。

    后来发现,是因为main函数中,binaryTreeRoot在经历了createTree之后,仍然是NULL,这是为什么呢?

    看过上面的内容,就明白了,错在createTree函数的传参。createTree函数的形参root在new node的时候便指向了一块新的内存地址了,而此时,实参binaryTreeRoot是没有任何变化的,仍然指向NULL。所以之后进行中序遍历,肯定会报错。

    这个时候,我们在传参时,因为我们需要操作的是传入的实参指针而不是形参指针,就需要把binaryTreeRoot的这个指针的地址传进去(和经典的swap例子一样的),才能起到一个真正的、数据双向绑定的效果,即:

    int main()
    {
    while (cin >> s)
    {
    node *binaryTreeRoot = NULL;
    len = 0;
    createTree(&binaryTreeRoot);
    
    midOrdTrave(binaryTreeRoot);
    cout << endl;
    }
    
    return 0;
    }

    这时候,createTree接收到的参数是地址的地址,也就相当于一个二重指针,所以在定义形参时,需要做一定修改,即

    //建树
    void createTree(node **root)

    在该函数内使用时,**root为被指向的node,*root为指向节点的指针,root为指针的地址。

    我们在修改节点内容时,便应该使用(*root->c=new_char)这样的方式来更新。但直接使用会报编译错误,所以我们使用一个tmp指针来过度。

    //创建一个新节点
    node *tmp = new node;
    tmp->c = c;
    tmp->left = NULL;
    tmp->right = NULL;
    
    *root = tmp;
    
    //因为字符串s是线序遍历,所以这里根据先序遍历的顺序构造树
    createTree(&(tmp->left));
    createTree(&(tmp->right));

    后两行递归也是一样的道理。

    那么完整的更新后的代码如下(也可以看题解,一样的):

    //根据二叉树的前序遍历字符串,构建树,并输出中序遍历结果
    #include <bits/stdc++.h>
    using namespace std;
    
    string s;
    int len; //每次遍历到的字符串中字符的index
    
    //定义二叉树的节点
    struct node
    {
    char c;
    node *left;
    node *right;
    };
    
    //建树
    void createTree(node **root)
    {
    if (len >= s.length())
    return; //到最后一个字符了,结束返回(字符串最后3个字符一定是###)
    char c = s[len++];
    
    if (c == '#')
    {
    *root = NULL;
    return;
    }
    else
    {
    //创建一个新节点
    node *tmp = new node;
    tmp->c = c;
    tmp->left = NULL;
    tmp->right = NULL;
    
    *root = tmp;
    
    //因为字符串s是线序遍历,所以这里根据先序遍历的顺序构造树
    createTree(&(tmp->left));
    createTree(&(tmp->right));
    }
    }
    
    void midOrdTrave(node *node)
    {
    //中序遍历
    if (node != NULL)
    {
    midOrdTrave(node->left);
    cout << node->c << " ";
    midOrdTrave(node->right);
    }
    return;
    }
    
    int main()
    {
    while (cin >> s)
    {
    node *binaryTreeRoot = NULL;
    len = 0;
    createTree(&binaryTreeRoot);
    
    midOrdTrave(binaryTreeRoot);
    cout << endl;
    }
    
    return 0;
    }
    
    
  • 您还可以看一下 韦语洋(Lccee)老师的一机一码加密、被破解自动销毁随时授权回收升级系列视频课程课程中的 演示误报效果,一些被误报的特征的解除方式(重要)小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    每次循环改变数组位置会影响之后的循环结果,因为每次循环都是基于当前数组的操作,而不是原始数组的操作。例如,第一次循环改变数组的位置会影响第二次循环的结果。为了避免这种情况,可以考虑使用复制原始数组的方式来操作每个循环。以下是示例代码:

    // 原始数组
    int arr[] = {1, 2, 3, 4, 5};
    
    // 复制数组
    int copiedArr[sizeof(arr)/sizeof(int)];
    memcpy(copiedArr, arr, sizeof(arr));
    
    // 操作复制后的数组
    for(int i = 0; i < sizeof(arr)/sizeof(int); i++) {
        int temp = copiedArr[i];
        copiedArr[i] = copiedArr[sizeof(arr)/sizeof(int)-1];
        copiedArr[sizeof(arr)/sizeof(int)-1] = temp;
    }
    
    // 输出复制后的数组和原始数组
    for(int i = 0; i < sizeof(arr)/sizeof(int); i++) {
        cout<<copiedArr[i]<<" ";
    }
    cout<<endl;
    for(int i = 0; i < sizeof(arr)/sizeof(int); i++) {
        cout<<arr[i]<<" ";
    }
    cout<<endl;
    

当然存在,否则改了个寂寞