使用具有自动调整大小的默认整数数组在java中实现堆栈

Posted

技术标签:

【中文标题】使用具有自动调整大小的默认整数数组在java中实现堆栈【英文标题】:Stack implementation in java using default integer array with auto resize 【发布时间】:2021-12-24 18:34:17 【问题描述】:

所以我试图在 java 中创建一个更省时的堆栈实现,但我不知道如何让它更快地工作。这是我的代码:

import java.util.Scanner;

public class A 

    public static void main(String[] args) 
        int[] n = new int[0];

        Scanner scan = new Scanner(System.in);
        loop: while(true)
            String stringy = scan.next();
            switch(stringy)
                case "push":
                    int x = scan.nextInt();
                    n = push(x, n);
                    System.out.println("ok");
                    break;
                case "pop":
                    n = pop(n);
                    break;
                case "exit":
                    System.out.println("bye");
                    break loop;
                case "size":
                    System.out.println(n.length);
                    break;
                case "back":
                    back(n);
                    break;
                case "clear":
                    n = clear();
                    System.out.println("ok");
                    break;

            
        

    
    static int[] push(int n, int[] x) 
        int[] z = new int[x.length + 1];
        for (int i = 0; i < x.length; i++)
            z[i] = x[i];
        
        z[x.length] = n;
        return z;
    


    static int[] pop(int[] x)
        int z[] = new int[x.length-1];
        for(int i = 0; i < z.length; i++)
            z[i] = x[i];
        
        System.out.println(x[x.length-1]);
        return z;
    
    static void back(int[] x)
        System.out.println(x[x.length-1]);
    
    static int[] clear()
        int x[] = new int[0];
        return x;
    

简要说明: 程序从扫描仪中获取值。根据输入的单词,程序会继续执行相应的指令,如推送、弹出、返回……它会打印出预期的值以通过 ok 进行控制台。到目前为止,除了性能外,一切都按预期正常工作。 如您所见,在 push 和 pop 方法中,我的程序创建新数组并复制所采用数组的值 x 并添加 1 个索引和推送值或删除弹出值。这种方法似乎相当缓慢且效率低下。如果不从 java 库中选择 arraylist 或其他类,我找不到更有效的方法。但我必须使用默认整数数组。还有其他问题会恶化程序的性能吗? 如何让我的程序运行得更快?

【问题讨论】:

你所说的“更快”是什么意思?你想推多少个数字?唯一/我的IDE抱怨:“使用System.arraycopy()”,用于pushSystem.arraycopy(x, 0, z, 0, x.length);(而不是for循环),用于popSystem.arraycopy(x, 0, z, 0, z.length);(而不是for循环;)跨度> 每次可以将一个元素压入数组。我的目标是使用通用数组,不使用数组复制或从库中导入其他类,并使其工作速度比现在更快 当使用“通用数组”时,您还必须区分:scan.nextXXX(push) ...但arraycopy 适用于所有类型的数组(并且比循环更可取)。 . 【参考方案1】:

您可以在方法之外创建成员变量来跟踪数组及其大小(类似于数组列表的实现方式),无需在每次需要弹出/推送时重新复制整个数组。

您将需要 2 个变量,数组本身和大小(将根据您的操作扩展/缩小)

你最好创建一个新类,我将其命名为 CustomStack

public class CustomStack

    private int[] elements = new int[10];  // instantiated with a size of 10
    private int size;  // To track how many ints we currently have
....

您现在可以在方法中访问数组和大小。

所以首先你需要 push 方法,但是这里有一个技巧,如果我已经达到了数组的最大大小怎么办? (即:数组中已经有 10 个数字),你需要解决这个问题,解决这个问题的一种已知方法是创建一个新数组,其大小是当前数组的两倍,然后将所有值复制到新数组中。

private void validateArraySize()

    if (size == elements.length)
    
        int[] temp = new int[elements.length * 2]; //double the size
        System.arraycopy(elements, 0, temp, 0, elements.length);  // copy the array
        elements = temp; //set our member variable array to the new array
    

以及推送方式:

public void push(int n)

     validateArraySize(); // The previos method to check if we can safely insert the value
     elements[size] = n;
     size++;

关于pop方法,很简单,只需要检查数组中是否有整数即可:

 public int pop()
 
     int valueRemoved = 0;
     if (size == 0)
        System.out.println("No elements found to pop");
     else
     
         valueRemoved = elements[size - 1]; //Get the last value
         elements[size - 1] = 0;  // remove the last value
         size--;
      
      return valueRemoved; // return removed value
 

整个班级会是这样的:

public class CustomStack

    private int[] elements = new int[10];
    private int size;

    public void push(int n)
    
        validateArraySize();
        elements[size] = n;
        size++;
    

    private void validateArraySize()
    
        if (size == elements.length)
        
            int[] temp = new int[elements.length * 2];
            System.arraycopy(elements, 0, temp, 0, elements.length);
            elements = temp;
        
    

    public int pop()
    
        int valueRemoved = 0;
        if (size == 0)
            System.out.println("No elements found to pop");
        else
        
            valueRemoved = elements[size - 1];
            elements[size - 1] = 0;
            size--;
        
        return valueRemoved;
    

    public int getSize()
    
        return size;
    

    public void back()
    
        if (size == 0)
            System.out.println("No elements found");
        else
            System.out.println(elements[size - 1]);
    

    public void clear()
    
        elements = new int[10];
    

你的主要方法将变成:

 public static void main(String[] args) 
        CustomStack customStack = new CustomStack();

        Scanner scan = new Scanner(System.in);
        loop: while(true)
            String stringy = scan.next();
            switch(stringy)
                case "push":
                    int x = scan.nextInt();
                    customStack.push(x);
                    System.out.println("ok");
                    break;
                case "pop":
                    int val = customStack.pop();
                    System.out.println(val + " is popped");
                    break;
                case "exit":
                    System.out.println("bye");
                    break loop;
                case "size":
                    System.out.println(customStack.getSize());
                    break;
                case "back":
                    customStack.back();
                    break;
                case "clear":
                    customStack.clear();
                    System.out.println("ok");
                    break;

            
        

【讨论】:

运行速度更慢,谢谢你的努力 @PBP_EnderLord 嘿,伙计,你是如何进行基准测试的?这肯定会更快,因为我们只在需要时复制数组,这意味着 push 和 pop 大部分时间都是常数 O(1) 这就是问题所在,我看不出它是如何让程序运行的。但是时间差很小,在测试用例中,你的命题平均慢了 ~0,001-0,0015 秒

以上是关于使用具有自动调整大小的默认整数数组在java中实现堆栈的主要内容,如果未能解决你的问题,请参考以下文章

PhoneGap:iOS 7 中的 UIPickerView 不会像在 iOS 6 中那样自动调整字体大小。关于如何在 iOS 7 中实现的任何解决方案?

在组件的持久化中实现 `Auto` 属性

自定义视图不使用自动布局调整大小

遍历整数数组所有组合的算法

UITextView自动调整大小以调整单行iOS Objective -C

如何在 Flutter 中实现具有自动完成和搜索等功能的列表