Is it possible to change my recursive method to iterative?

拟墨画扇 提交于 2021-01-07 03:00:53

问题


I'm writing a quicksort algorithm to sort numbers with random pivot. How can I change my quicksort methods from recursive to iterative? I have one sort method which is recursive, but I need the iterative method. Is it possible to change from recursive to iterative in just the sort method or do I have to change the whole code?

here is all my code

public class Main {

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        ArrayList time = new ArrayList();
        for (int k = 1; k < 1000000; k++) {
            time.add(k);
        }

        int[] tall = new int[1000000];
        int index = 0;
        int n = 1000000;

        File text = new File("/Users/sasan/IdeaProjects/File.txt");

        try {
            Scanner scan = new Scanner(text);

            while (scan.hasNextLine() && index < 1000000) {
                tall[index] = scan.nextInt();
                index++;
            }
            scan.close();
        } catch (IOException e) {
            System.out.println("Problem with file");
            e.printStackTrace();
        }

        int l = tall.length;

        sort(tall, 0, l-1);

        System.out.println("Sorted array");
        printArray(tall);

        System.out.println("");

        long end = System.currentTimeMillis();
        System.out.print("Execution Time is: ");
        System.out.print((end - start));
    }

    static void random(int tall[],int low,int high)
    {
        Random rand= new Random();
        int pivot = rand.nextInt(high-low)+low;

        int temp1=tall[pivot];
        tall[pivot]=tall[high];
        tall[high]=temp1;
    }

    /* This function takes last element as pivot,
    places the pivot element at its correct
    position in sorted array, and places all
    smaller (smaller than pivot) to left of
    pivot and all greater elements to right
    of pivot */
    static int partition(int tall[], int low, int high)
    {
        // pivot is choosen randomly
        random(tall,low,high);
        int pivot = tall[high];

        int i = (low-1); // index of smaller element
        for (int j = low; j < high; j++)
        {
            // If current element is smaller than or
            // equal to pivot
            if (tall[j] < pivot)
            {
                i++;

                // swap arr[i] and arr[j]
                int temp = tall[i];
                tall[i] = tall[j];
                tall[j] = temp;
            }
        }

        // swap arr[i+1] and arr[high] (or pivot)
        int temp = tall[i+1];
        tall[i+1] = tall[high];
        tall[high] = temp;

        return i+1;
    }

    /* The main function that implements QuickSort()
    tall[] --> Array to be sorted,
    low --> Starting index,
    high --> Ending index */
    static void sort(int tall[], int low, int high)
    {
        if (low < high)
        {
            /* pi is partitioning index, tall[pi] is
            now at right place */
            int pi = partition(tall, low, high);

            // Recursively sort elements before
            // partition and after partition
            sort(tall, low, pi-1);
            sort(tall, pi+1, high);
        }
    }

    /* A utility function to print array of size n */
    static void printArray(int tall[])
    {
        int n = tall.length;
        for (int i = 0; i < n; ++i)
            System.out.print(tall[i]+" ");
        System.out.println();
    }

    // Driver Code
}

回答1:


You can generally always turn a recursive method into an iterative method, though the point about using recursion is that you usually choose it when it's most convenient to do so. A divide-and-conquer algorithm such as quicksort is precisely a good candidate for recursion.

To turn a recursive method into an iterative method, you basically use a 'stack' object (and Java provides the Stack class to assist with this): this essentially stores what parameters need to be operated on on each iteration. Then, whereas before you would have called into your recursive method, you put on top of your stack the parameters that would have been used to call it. Each iteration does the equivalent of "returning" from the method by taking the latest parameters off the top of the stack. (Essentially, you're simulating the process that Java goes through under the hood when you call a method.)

So the pattern looks like this:

Stack<Paraneters> stack = new Stack();
stack.push(new Parameters(0, size);
while (!stack.empty()) {
    Parameters params = stack.pop();
    int lo = params.lo;
    int hi = params.hi;
    
    if (lo < hi) {
        int pivot = partition(lo, hi);
        stack.push(new Parameters(lo, pivot-1));
        stack.push(new Parameters(pivot+1, hi));
    }
}

For this simple example, the Parameters object could actually just be a 2-length int array, but for more complex combinations of parameters you may end up constructing a wrapper class. (Another reason why using recursion can be more convenient in practice.)



来源:https://stackoverflow.com/questions/65386916/is-it-possible-to-change-my-recursive-method-to-iterative

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!