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比公认的答案有用得多。这里需要注意的重要一点是,递归算法的迭代版本的复杂性是相同的。因此,唯一的好处是我们可以通过使用堆和虚拟内存来避免堆栈溢出。