快速排序的非递归实现

问题来源

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进栈。当栈为空时循环结束。

总结
  1. 学习了指向函数的指针的使用方法
  2. 使用栈来模拟函数调用
  3. 如果node包含两个参数,一个子序列是起始值,一个子序列是结束值,分别对应于递归方法中的l和r,那么写起来更简单,不需要startIndex这个变量,但是需要更多的内存。
  4. 使用本方法迭代的次数比递归方法多,因为需要处理子序列只有一个的情况。