Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 查看排序-快速排序迭代?_Algorithm_Sorting - Fatal编程技术网

Algorithm 查看排序-快速排序迭代?

Algorithm 查看排序-快速排序迭代?,algorithm,sorting,Algorithm,Sorting,我在看各种各样的东西。请注意,这不是家庭作业,我正在期末考试中,我只是想做好准备,如果出现这种情况。 我无法找到一种可靠的方法来迭代进行快速排序。是否可能,如果可能,如何实现 #include <stdio.h> #include <conio.h> #define MAXELT 100 #define INFINITY 32760 // numbers in list should not exceed

我在看各种各样的东西。请注意,这不是家庭作业,我正在期末考试中,我只是想做好准备,如果出现这种情况。 我无法找到一种可靠的方法来迭代进行快速排序。是否可能,如果可能,如何实现

#include <stdio.h>
#include <conio.h>

#define MAXELT          100
#define INFINITY        32760         // numbers in list should not exceed
                                      // this. change the value to suit your
                                      // needs
#define SMALLSIZE       10            // not less than 3
#define STACKSIZE       100           // should be ceiling(lg(MAXSIZE)+1)

int list[MAXELT+1];                   // one extra, to hold INFINITY

struct {                              // stack element.
        int a,b;
} stack[STACKSIZE];

int top=-1;                           // initialise stack

int main()                           // overhead!
{
    int i=-1,j,n;
    char t[10];
    void quicksort(int);

    do {
        if (i!=-1)
            list[i++]=n;
        else
            i++;
        printf("Enter the numbers <End by #>: ");
        fflush(stdin);
        scanf("%[^\n]",t);
        if (sscanf(t,"%d",&n)<1)
        break;
    } while (1);

    quicksort(i-1);

    printf("\nThe list obtained is ");
    for (j=0;j<i;j++)
        printf("\n %d",list[j]);

    printf("\n\nProgram over.");
    getch();
    return 0;       // successful termination.
}

void interchange(int *x,int *y)        // swap
{
    int temp;

    temp=*x;
    *x=*y;
    *y=temp;
}

void split(int first,int last,int *splitpoint)
{
    int x,i,j,s,g;

    // here, atleast three elements are needed
    if (list[first]<list[(first+last)/2]) {  // find median
        s=first;
        g=(first+last)/2;
    }
    else {
        g=first;
        s=(first+last)/2;
    }
    if (list[last]<=list[s]) 
        x=s;
    else if (list[last]<=list[g])
        x=last;
    else
        x=g;
    interchange(&list[x],&list[first]);      // swap the split-point element
                                             // with the first
    x=list[first];
    i=first+1;                               // initialise
    j=last+1;
    while (i<j) {
        do {                                 // find j 
            j--;
        } while (list[j]>x);
        do {
            i++;                             // find i
        } while (list[i]<x);
        interchange(&list[i],&list[j]);      // swap
    }
    interchange(&list[i],&list[j]);          // undo the extra swap
    interchange(&list[first],&list[j]);      // bring the split-point 
                                             // element to the first
    *splitpoint=j;
}

void push(int a,int b)                        // push
{
    top++;
    stack[top].a=a;
    stack[top].b=b;
}

void pop(int *a,int *b)                       // pop
{
    *a=stack[top].a;
    *b=stack[top].b;
    top--;
}

void insertion_sort(int first,int last)
{
    int i,j,c;

    for (i=first;i<=last;i++) {
        j=list[i];
        c=i;
        while ((list[c-1]>j)&&(c>first)) {
            list[c]=list[c-1];
            c--;
        }
        list[c]=j;
    }
}

void quicksort(int n)
{
    int first,last,splitpoint;

    push(0,n);
    while (top!=-1) {
        pop(&first,&last);
        for (;;) {
            if (last-first>SMALLSIZE) {
                // find the larger sub-list
                split(first,last,&splitpoint);
                // push the smaller list
                if (last-splitpoint<splitpoint-first) {
                    push(first,splitpoint-1);
                    first=splitpoint+1;
                }
                else {
                    push(splitpoint+1,last);
                    last=splitpoint-1;
                }
            }
            else {  // sort the smaller sub-lists
                    // through insertion sort
                insertion_sort(first,last);
                break;
            }
        }
    }                        // iterate for larger list
}

// End of code.
取自

你试过了吗


当使用数组实现递归时,这只是常见的快速排序。

这是我的工作。告诉我是否有任何可能的改进

这段代码是从《数据结构》一书中完成的,西摩·利普舒茨(Seymour LipschutzPage-173),Mc GrawHill,Schaum的大纲系列

#include <stdio.h>
#include <conio.h>
#include <math.h>

#define SIZE 12

struct StackItem
{
    int StartIndex;
    int EndIndex;
};
struct StackItem myStack[SIZE * SIZE];
int stackPointer = 0;

int myArray[SIZE] = {44,33,11,55,77,90,40,60,99,22,88,66};

void Push(struct StackItem item)
{
    myStack[stackPointer] = item;
    stackPointer++;
}

struct StackItem Pop()
{
    stackPointer--;
    return myStack[stackPointer];
}

int StackHasItem()
{
    if(stackPointer>0)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

void ShowStack()
{
    int i =0;

    printf("\n");

    for(i=0; i<stackPointer ; i++)
    {
        printf("(%d, %d), ", myStack[i].StartIndex, myStack[i].EndIndex);
    }

    printf("\n");
}

void ShowArray()
{
    int i=0;

    printf("\n");

    for(i=0 ; i<SIZE ; i++)
    {
        printf("%d, ", myArray[i]);
    }

    printf("\n");
}

void Swap(int * a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

int Scan(int *startIndex, int *endIndex)
{
    int partition = 0;
    int i = 0;

    if(*startIndex > *endIndex)
    {
        for(i=*startIndex ; i>=*endIndex ; i--)
        {
            //printf("%d->", myArray[i]);
            if(myArray[i]<myArray[*endIndex])
            {
                //printf("\nSwapping %d, %d", myArray[i], myArray[*endIndex]);
                Swap(&myArray[i], &myArray[*endIndex]);
                *startIndex = *endIndex;
                *endIndex = i;
                partition = i;
                break;
            }
            if(i==*endIndex)
            {
                *startIndex = *endIndex;
                *endIndex = i;
                partition = i;
            }
        }
    }
    else if(*startIndex < *endIndex)
    {
        for(i=*startIndex ; i<=*endIndex ; i++)
        {
            //printf("%d->", myArray[i]);
            if(myArray[i]>myArray[*endIndex])
            {
                //printf("\nSwapping %d, %d", myArray[i], myArray[*endIndex]);
                Swap(&myArray[i], &myArray[*endIndex]);
                *startIndex = *endIndex;
                *endIndex = i;
                partition = i;
                break;
            }
            if(i==*endIndex)
            {
                *startIndex = *endIndex;
                *endIndex = i;
                partition = i;
            }
        }
    }

    return partition;
}

int GetFinalPosition(struct StackItem item1)
{
    struct StackItem item = {0};
    int StartIndex = item1.StartIndex ;
    int EndIndex = item1.EndIndex;
    int PivotIndex = -99;

    while(StartIndex != EndIndex)
    {
        PivotIndex = Scan(&EndIndex, &StartIndex);

        printf("\n");
    }

    return PivotIndex;
}

void QuickSort()
{
    int median = 0; 
    struct StackItem item;  
    struct StackItem item1={0};
    struct StackItem item2={0};

    item.StartIndex = 0;
    item.EndIndex = SIZE-1;

    Push(item);

    while(StackHasItem())
    {
        item = Pop();

        median = GetFinalPosition(item);

        if(median>=0 && median<=(SIZE-1))
        {
            if(item.StartIndex<=(median-1))
            {
                item1.StartIndex = item.StartIndex;
                item1.EndIndex = median-1;
                Push(item1);
            }       
            if(median+1<=(item.EndIndex))
            {
                item2.StartIndex = median+1;
                item2.EndIndex = item.EndIndex;
                Push(item2);
            }
        }

        ShowStack();
    }
}

main()
{
    ShowArray();
    QuickSort();
    ShowArray();
}

除了在其他文章中给出的实际实现之外,我将尝试给出一个更一般的答案

是否可能,如果可能,如何实现

#include <stdio.h>
#include <conio.h>

#define MAXELT          100
#define INFINITY        32760         // numbers in list should not exceed
                                      // this. change the value to suit your
                                      // needs
#define SMALLSIZE       10            // not less than 3
#define STACKSIZE       100           // should be ceiling(lg(MAXSIZE)+1)

int list[MAXELT+1];                   // one extra, to hold INFINITY

struct {                              // stack element.
        int a,b;
} stack[STACKSIZE];

int top=-1;                           // initialise stack

int main()                           // overhead!
{
    int i=-1,j,n;
    char t[10];
    void quicksort(int);

    do {
        if (i!=-1)
            list[i++]=n;
        else
            i++;
        printf("Enter the numbers <End by #>: ");
        fflush(stdin);
        scanf("%[^\n]",t);
        if (sscanf(t,"%d",&n)<1)
        break;
    } while (1);

    quicksort(i-1);

    printf("\nThe list obtained is ");
    for (j=0;j<i;j++)
        printf("\n %d",list[j]);

    printf("\n\nProgram over.");
    getch();
    return 0;       // successful termination.
}

void interchange(int *x,int *y)        // swap
{
    int temp;

    temp=*x;
    *x=*y;
    *y=temp;
}

void split(int first,int last,int *splitpoint)
{
    int x,i,j,s,g;

    // here, atleast three elements are needed
    if (list[first]<list[(first+last)/2]) {  // find median
        s=first;
        g=(first+last)/2;
    }
    else {
        g=first;
        s=(first+last)/2;
    }
    if (list[last]<=list[s]) 
        x=s;
    else if (list[last]<=list[g])
        x=last;
    else
        x=g;
    interchange(&list[x],&list[first]);      // swap the split-point element
                                             // with the first
    x=list[first];
    i=first+1;                               // initialise
    j=last+1;
    while (i<j) {
        do {                                 // find j 
            j--;
        } while (list[j]>x);
        do {
            i++;                             // find i
        } while (list[i]<x);
        interchange(&list[i],&list[j]);      // swap
    }
    interchange(&list[i],&list[j]);          // undo the extra swap
    interchange(&list[first],&list[j]);      // bring the split-point 
                                             // element to the first
    *splitpoint=j;
}

void push(int a,int b)                        // push
{
    top++;
    stack[top].a=a;
    stack[top].b=b;
}

void pop(int *a,int *b)                       // pop
{
    *a=stack[top].a;
    *b=stack[top].b;
    top--;
}

void insertion_sort(int first,int last)
{
    int i,j,c;

    for (i=first;i<=last;i++) {
        j=list[i];
        c=i;
        while ((list[c-1]>j)&&(c>first)) {
            list[c]=list[c-1];
            c--;
        }
        list[c]=j;
    }
}

void quicksort(int n)
{
    int first,last,splitpoint;

    push(0,n);
    while (top!=-1) {
        pop(&first,&last);
        for (;;) {
            if (last-first>SMALLSIZE) {
                // find the larger sub-list
                split(first,last,&splitpoint);
                // push the smaller list
                if (last-splitpoint<splitpoint-first) {
                    push(first,splitpoint-1);
                    first=splitpoint+1;
                }
                else {
                    push(splitpoint+1,last);
                    last=splitpoint-1;
                }
            }
            else {  // sort the smaller sub-lists
                    // through insertion sort
                insertion_sort(first,last);
                break;
            }
        }
    }                        // iterate for larger list
}

// End of code.
首先,让我们看一看使递归算法迭代意味着什么

例如,我们想要一个函数sumn,它将0到n之间的数字相加

当然,这是

sum(n) = 
  if n = 0
    then return 0
    else return n + sum(n - 1)
当我们试图计算像sum100000这样的东西时,我们很快就会看到这种递归算法有它的局限性——堆栈溢出将会发生

因此,作为解决方案,我们使用迭代算法来解决相同的问题

sum(n) =
   s <- 0
   for i in 0..n do
     s <- s + i
   return s
然而,需要注意的是,这个实现与上面的递归求和算法完全不同。我们没有以某种方式修改原始算法以获得迭代版本,我们基本上只是找到了一个非递归算法——具有不同的、可以说更好的性能特征——来解决相同的问题

sum(n) =
   s <- 0
   for i in 0..n do
     s <- s + i
   return s
这是使算法迭代的第一个方面:找到一个不同的迭代算法来解决相同的问题

sum(n) =
   s <- 0
   for i in 0..n do
     s <- s + i
   return s
在某些情况下,可能根本没有这样的迭代版本

第二种算法适用于所有递归算法。通过显式引入递归隐式使用的堆栈,可以将任何递归转换为迭代。现在,该算法将具有与原始算法完全相同的特性,并且堆栈将像递归版本一样随时间增长。它不会那么容易溢出,因为它使用传统内存而不是调用堆栈,并且它是迭代的,但它仍然是相同的算法


至于快速排序:如果不存储递归所需的数据,没有不同的公式。当然,您可以像Ehsan所展示的那样为它们使用显式堆栈。因此,您可以一如既往地生成迭代版本。

如果您自己管理堆栈而不是使用调用堆栈,则任何递归算法都可以作为循环实现。这就足够了吗?+1比公认的答案有用得多。这里需要注意的重要一点是,递归算法的迭代版本的复杂性是相同的。因此,唯一的好处是我们可以通过使用堆和虚拟内存来避免堆栈溢出。