簡體   English   中英

雙向鏈表中的迭代快速排序 C

[英]Iterative QuickSort in Doubly Linked List in C

我這里有一個 function 來快速排序一個使用遞歸方法的雙向鏈表。 我想知道如何將此 function 從遞歸更改為迭代快速排序。 我一直在嘗試,但我無法理解它是如何完成的。

編輯:我修改了代碼,但無法對列表進行排序。 我只是遵循了關於如何使用數組實現快速排序的算法。 它雖然沒有錯誤。

#include <stdio.h>
#include <stdlib.h>

struct Node
{
    int val;
    struct Node *next;
    struct Node *prev;
};

struct Stack
{
    struct Node* top;
};

typedef struct Stack *stackPtr;

struct Node *CreateNode(int data)
{
    struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
    newNode->next = newNode->prev = NULL;
    newNode->val = data;
    
    return newNode;
}

stackPtr CreateStack()
{
    stackPtr stack = (stackPtr)malloc(sizeof(struct Stack));
    stack->top = NULL;
}

void Push(stackPtr stack, int data)
{
    struct Node *newNode = CreateNode(data);
    newNode->next = stack->top;
    stack->top = newNode;   
}

void Pop(stackPtr stack)
{
    struct Node *temp;
    temp = stack->top;
    stack->top = stack->top->next;
    free(temp);
}

struct Node *partition(struct Node *left, struct Node *right)
{
    struct Node *pivot = right;
    struct Node *i = left->prev;
    struct Node *ptr;
    for (ptr = left; ptr != right; ptr = ptr->next)
    {
        if (ptr->val <= pivot->val)
        {
            i = (i == NULL ? left : i->next);
            int temp = i->val;
            i->val = ptr->val;
            ptr->val = temp;
        }
    }
    i = (i == NULL ? left : i->next);
    int temp = i->val;
    i->val = pivot->val;
    pivot->val = temp;
    return i;
}
void QuickSort(struct Node *left, struct Node *right)
{    
    stackPtr auxStack = CreateStack();
    Push(auxStack, left->val);
    Push(auxStack, right->val);
    
    while(auxStack->top != NULL)
    {
        Pop(auxStack);
    }
    
    struct Node *pivot = partition(left, right);
    
    if((pivot->val - 1) > left->val)
    {
        Push(auxStack, left->val);
        Push(auxStack, (pivot->val - 1));
    }
    
    if((pivot->val + 1) < right->val)
    {
        Push(auxStack, (pivot->val + 1));
        Push(auxStack, right->val);
    }
}

int main()
{
    struct Node *head = malloc(sizeof(struct Node));
    head->val = 2;
    head->prev = NULL;
    struct Node *l1 = malloc(sizeof(struct Node));
    l1->val = 8;
    l1->prev = head;
    head->next = l1;
    struct Node *l2 = malloc(sizeof(struct Node));
    l2->val = 3;
    l2->prev = l1;
    l1->next = l2;
    struct Node *l3 = malloc(sizeof(struct Node));
    l3->val = 5;
    l3->prev = l2;
    l2->next = l3;
    struct Node *l4 = malloc(sizeof(struct Node));
    l4->val = 10;
    l4->prev = l3;
    l3->next = l4;
    l4->next = NULL;
    // 2<=>8<=>3<=>5<=>10=>NULL

    QuickSort(head, l4);
    while (head != NULL)
    {
        printf("%d ", head->val);
        head = head->next;
    }
    return 0;
}

假設您有一個有效的遞歸快速排序 function:

void quicksort_rec(int *a, const int *end)
{
    if (a + 1 < end) {
        int *pivot = partition(a, end);

        quicksort_rec(a, pivot);
        quicksort_rec(pivot + 1, end);
    }
}

(這是對數組的快速排序,它采用指向數組開頭和(不包括)結尾的指針形式的范圍。不要在意分區 function 的詳細信息。)

當您遞歸調用quicksort_rec時,被調用函數的局部變量存儲在調用堆棧中:隨着遞歸深度的增加,“父”遞歸的樞軸和范圍仍然可用。

如果你想把它變成一個迭代的function,你必須手動維護一個堆棧。 (John Bollinger 在評論中比我更詳細、更好地描述了這一點。)

因此,不是調用quicksort(a, b) ,而是必須將ab壓入堆棧以“保存它們以備后用”。 最后壓入堆棧的東西是最先彈出的東西,所以接下來將對右側數組進行排序。

給定存儲指向int指針的堆棧實現,我們可以將上面的遞歸 function 轉換為迭代 function:

void quicksort_iter(int *a, int *end)
{
    Stack stack = {0};
    
    push(&stack, a);
    push(&stack, end);

    while (isempty(&stack)) {
        end = pop(&stack);
        a = pop(&stack);
        
        if (a + 1 < end) {
            int *pivot = partition(a, end);
            
            push(&stack, a);
            push(&stack, pivot);
        
            push(&stack, pivot + 1);
            push(&stack, end);
        }
    }
}

此代碼總是同時壓入或彈出兩個項目。 請注意,開始和結束指針必須按照它們被壓入的相反順序彈出。 您還可以創建一個 pwo 指針結構,並始終推送一個這樣的結構,這可能更干凈。 如果已知子數組少於兩個項目,您還可以通過不將子數組壓入堆棧來優化這一點。

確切的實現留給讀者,yadda,yadda,... :)這里是上面代碼的完整實現,可以幫助您入門。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM