【问题标题】:How to fill an array of ints while keeping its order?如何在保持顺序的同时填充整数数组?
【发布时间】:2016-01-17 20:53:49
【问题描述】:

我正在尝试做一个简单的练习,我想从用户输入中填充一个整数数组,并保持输入的顺序,这样就不需要在用户完成后对数组进行排序。

假设数组的状态是这样的:{ 3, 5, 7, 8, 9,-,-,-,-,- }(- 表示空)

现在在这种状态下,比如输入6,arr[1]后面的所有元素都应该向前移动一位,这样6就可以放在arr[2]中了。

#include "stdafx.h"
#include <iostream>
using namespace std;

int main()
{
    bool ok = true;
    int x       // the input
        , n = 0 // to keep track of numbers already in the array
        , i, j  // to iterate in loops
        , arr[10];

    cout << "Enter 10 numbers: \n";
    while (cin >> x) {
        if (n == 0) { arr[n] = x; n++; } // for the first entry.

        else if (x < arr[0]) { // is x lower than the first element in the array?
            for (i = n; i > 0; i--)
                arr[i] = arr[i - 1];
            arr[0] = x; n++;
        }

        else if (x > arr[n - 1]) { // is x greater than the top of already addded 
                                   // elements to the array?
            arr[n] = x; n++;
        }

        else { // when x is in between of elements. Also I think the problem is here.
            for (i = 0; i < n && ok; i++)
                if (x > arr[i] && x < arr[i + 1]) {
                    for (j = n; j > i + 1; j--)
                        arr[j] = arr[j - 1];
                    ok = false;
                }
            arr[i + 1] = x; n++;
        }

        if (n == 10) break; // if you reached to end of the array, break while.
    }

    for (i = 0; i < 10; i++)
        cout << arr[i] << " ";

    cin.get();
    cin.get();
}

这段代码有很多问题,但是当我尝试输入时:1、10、2、3、4、5、6、7、8、9 程序不会将 10 移动到数组结束,输出:1, 10, 2, 3, 4, 5, 6, 7, 8, 9。

【问题讨论】:

  • 您所说的是“容器”。您可以使用二叉树来做到这一点,但最好的是 AVL 树。你仍然可以这样做,但是使用树来代替更有效。 stl 中已经有容器,请参阅 Pustovalov 评论。
  • 你为什么不想使用 std::set 自动排序它的值?还是必须使用 C 风格的数组?
  • std::set&lt;int&gt; arr; while (cin &gt;&gt; x) arr.insert(x); 3 班轮。
  • @PierreEmmanuelLallemant AVL 不是最好的。 RB 更快。
  • @SashaMN:AVL 比红黑树更严格地平衡,导致插入和删除速度较慢,但​​检索速度更快(维基百科)。

标签: c++ arrays sorting console-application


【解决方案1】:

这里的问题是,for循环的递增步骤总是在前一个执行条件为真时执行。

    for (i = 0; i < n && ok; i++) // i is incremented
        if (x > arr[i] && x < arr[i + 1]) {
            for (j = n; j > i + 1; j--)
                arr[j] = arr[j - 1];
            ok = false;
        }
    arr[i + 1] = x; n++;

所以插入“2”后for循环的条件为真:

for (i = 0; i < n && ok; i++) 

然后执行 for 循环的主体并且 i 递增。 现在再次检查条件并评估为假,但 i 是 1 而不是预期值 0。

所以执行完之后

    arr[i + 1] = x; n++;

你的数组看起来像: [1] [10] [2]

【讨论】:

  • 好心人在这里给我写了一些非常好的答案/想法,但我将你的答案/想法标记为答案,因为你指出的是确切错误我的代码。谢谢。
【解决方案2】:

您可以将std::vectorstd::upper_bound 结合使用,而不是原始数组,并对每个用户输入使用以下构造:

template<typename T>
typename std::vector<T>::iterator insertInOrder(std::vector<T> &v, T const &val){
  auto it = std::upper_bound(v.begin(), v.end(), val);
  v.insert(it, val);

  return it;
}

Live Demo

【讨论】:

    【解决方案3】:

    我想这是你的作业,你不能使用带有vector::insert() 的向量,也不能使用其他合适的标准容器或算法。

    我建议通过使用一个单一的通用方法来简化算法:尝试找到数组中 x 较慢的第一个元素。如果找到,则在正确的位置插入 x,否则,将其添加到末尾:

    while (cin >> x) {
        for (i=0, ok=false; i<n; i++ ) { // iterate for the general case
            if (x < arr[i]) {  // find first wher x is lower
                for (j = n; j>i; j--)  // move remaining elements
                    arr[j] = arr[j - 1];
                arr[i] = x;
                n++;
                ok = true;   // we've found the place and inserted x
                break; 
            }
        }
        if (!ok) {   // if we didn't insert until now, we have to add it at the end
            if (n<arrsize)
                arr[n++] = x; 
            else cerr << "Array full "<<endl; 
        }
    }
    

    这里是 live demo(arrsize 是一个定义为 10 的常量)。

    【讨论】:

      【解决方案4】:

      你可以试试:

              for (i = 0; i < n && ok; i++)
                  if (x > arr[i] && x < arr[i + 1]) {
                      for (j = n; j > i + 1; j--)
                          arr[j] = arr[j - 1];
      
                      // All elements moved - get out of the for-loop
                      break;
                  }
              arr[i + 1] = x; n++;
      

      但是,行

                  if (x > arr[i] && x < arr[i + 1]) {
      

      也会给你带来麻烦。

      如果你的数组成立

      2, 3, 4
      

      如果下一个输入是 3,则 if 语句永远不会为真,程序将失败。

      【讨论】:

      • 是的,break; !!!谢谢你。不,我知道。从一开始,我就只针对不相等的数字。
      【解决方案5】:

      数组对这种事情很不利.. 考虑使用链表, 你创建一个 Node 类,其中包含一个值和指向下一个节点的指针:

      class Node{
          int number;
          Node *nextNode;
      }
      

      还有一些 List 类处理主题的代码, 你会发现在两个其他节点之间插入一个节点要容易得多, 而不是将数组移动一千次。

      更好的信息 -> http://www.cprogramming.com/tutorial/lesson15.html

      【讨论】:

        【解决方案6】:

        也许这会有所帮助,所以

        #include <iostream>
        #include <algorithm>
        
        using namespace std;
        
        void inputInOrder(int *arr, int num){
        
            // Start from the end of array.
            // If newly added element is smaller then the element before it swap them.
        
            for(int i(num); i > 0; i--)
                if(arr[i] < arr[i-1])
                    std::swap(arr[i], arr[i-1]);
                else break;
            }
        
        
        int main()
        {
        
            int n;
            cout << "Number of elements: ";
            cin >> n;
        
        
            int *arr = new int[n];
        
            int input(0);
        
            for(int i(0); i < n; ++i){
                cout << "Insert element: ";
                cin >> input;
                arr[i] = input;  // you add a new element to the end of array
                // call a function that will move newly added element to the right place
                inputInOrder(arr, i);
            }
        
            for(int i(0); i < n; ++i)
                cout << arr[i] << " ";
        
            delete[] arr;
        
            return 0;
        }
        

        【讨论】:

          猜你喜欢
          • 2020-06-09
          • 2015-11-28
          • 1970-01-01
          • 2011-03-15
          • 1970-01-01
          • 2012-03-03
          • 1970-01-01
          • 1970-01-01
          • 2018-04-04
          相关资源
          最近更新 更多