快速排序的非递归实现
问题来源
https://leetcode.com/problems/largest-number/
Given a list of non negative integers, arrange them such that they form the largest number.
For example, given [3, 30, 34, 5, 9], the largest formed number is 9534330.
Note: The result may be very large, so you need to return a string instead of an integer.
需要对数组排序,比较的方法是对于两个整数n和m,设strn和strm是其对应的字符串,如果strn+strm > strm+strn,那么n>m。
递归版的快速排序
<c>
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
void swap(int *a ,int *b)
{
int t = *a;
*a = *b;
*b = t;
}
int partition(int array[],int l,int r)
{
int pivot = array[r];
int curpos = l;
int j ;
for( j = l;j<r;j++)
{
if(array[j] < pivot)
{
swap(&array[j],&array[curpos]);
curpos++;
}
}
swap(&array[r],&array[curpos]);
return curpos;
}
void quicksort(int array[],int l,int r)
{
int interval;
if(l < r)
{
interval = partition(array,l,r);
quicksort(array,l,interval-1);
quicksort(array,interval+1,r);
}
}
</c>
主要分为划分和递归调用排序。
#非递归快排
由递归向非递归的转变需要自己模拟函数调用的过程,这里我采用了栈的思想。由于栈的深度未知,使用链表来实现栈。
int mycmp( int i, int j)
{
char is[30], js[30];
itoa(i,is,10);
itoa(j,js,10);
char il[60],jl[60];
*il=*jl = ‘\0’;
strcat(il,is);
strcat(il,js);
strcat(jl,js);
strcat(jl,is);
return strcmp(il,jl);
}
//未完成排序部分的末尾
struct Node
{
int data;
struct Node * next;
};
void myQSort(int * num, int n, int (*mycmp)(int, int))
{
int startIndex = 0;//当前排序部分的起点
if(n < 2)
return;
struct Node * temp = (struct Node *)malloc(sizeof(struct Node));
struct Node * head = NULL;
temp->next = NULL;
temp->data = n-1;
temp->next = head;
head = temp;
int pivot = num[startIndex];
int Nodenum = 1;
int nextPivotIndex;
while (head)
{
pivot = num[startIndex];
//printf("startIndex is %d, head is",startIndex);
//temp = head;
//while(temp)
//{
// printf(" %d",temp->data);
// temp = temp->next;
//}
//printf("\nthe array is :");
//for(int i = 0; i< n; i++)
// printf("%d ",num[i]);
//printf("\n");
if (startIndex == head->data)
{
startIndex++;
temp = head->next;
free(head);
// printf("-----Nodenum is %d\n",--Nodenum);
head = temp;
continue;
}
nextPivotIndex = startIndex;
int tempE;
for (int i = startIndex+1; i <= head->data; i++)
{
if (mycmp(num[i],pivot)>0 )
{
nextPivotIndex++;
tempE = num[nextPivotIndex];
num[nextPivotIndex] = num[i];
num[i] = tempE;
}
}
if (startIndex == nextPivotIndex)
startIndex++;
else
{
num[startIndex] = num[nextPivotIndex];
num[nextPivotIndex] = pivot;
temp = (struct Node *)malloc(sizeof(struct Node));
temp->next = head;
temp->data = nextPivotIndex-1;
head = temp;
// printf("+++++Nodenum is %d\n",++Nodenum);
}
}
}
使用链表node
来表示栈,代表当前需处理子序列的终点,起始为·n-1·,函数mycmp
为比较函数。startIndex
为当前需处理函数的起始点。在while
循环中,如果startIndex
等于栈顶的值,那么将栈顶pop,否则进行处理,将比num[startIndex]
大的值放到子序列的前段,然后是num[startIndex]
,然后是比其小的数。如果没有比num[startIndex]
大的数,那么就简单的将startIndex
自增,否则建立一个新的node
并push进栈。当栈为空时循环结束。
总结
- 学习了指向函数的指针的使用方法
- 使用栈来模拟函数调用
- 如果
node
包含两个参数,一个子序列是起始值,一个子序列是结束值,分别对应于递归方法中的l和r,那么写起来更简单,不需要startIndex
这个变量,但是需要更多的内存。 - 使用本方法迭代的次数比递归方法多,因为需要处理子序列只有一个的情况。