簡體   English   中英

迭代有序遍歷

[英]Iterative Inorder Traversal

這是我用於迭代順序遍歷的函數。 但是當我執行它時,我遇到了分段錯誤。 我正在使用堆棧進行遍歷。 在給定程序中,我還有一個遞歸函數,用於順序遍歷以檢查我的create()函數是否正常工作。

我將節點推入堆棧,然后移到節點的左側,然后從堆棧中彈出節點,然后通過root=root->rlink將其打印並移至右側。

#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *llink;
struct node *rlink;
}Node;
typedef struct Stack
{
Node *a[10];
int top;
}stack;
void push(stack *s,Node *root)
{
if(s->top==9)
    printf("FULL");
else
{
    s->top++;
    s->a[s->top]=root;
}
}
Node *pop(stack *s)
{
    if(s->top==-1)
        printf("Empty");
    return s->a[s->top--];
}
void inorder(Node *root)
{
    stack s;
    s.top=-1;
    int flag=1;
    while(flag)
    {
    if(s.top!=9)
    {
        push(&s,root);
        root=root->llink;
    }
    else{
        if(s.top!=-1)
        {
            root=pop(&s);
            printf("%d",root->data);
            root=root->rlink;
        }
        else
            flag=0;
    }
    }
}
void inor(Node *root)
{
if(root!=NULL)
{
inor(root->llink);
printf("%d",root->data);
inor(root->rlink);
}
}
Node *create(Node *root,int key)
{
if(root==NULL)
{
root=(Node *)malloc(sizeof(Node));
root->data=key;
root->rlink=root->llink=NULL;
}
else
{
if(key>root->data)
{
    root->rlink=create(root->rlink,key);
}
else if(key<root->data)
{
root->llink=create(root->llink,key);
}
}
return root;
}
int main()
{
    Node *h=NULL;
    h=create(h,5);
    h=create(h,1);
    h=create(h,3);
    h=create(h,8);
    h=create(h,12);
    h=create(h,51);
    inorder(h);
    //inor(h);
}

正如我在主要評論中所診斷的那樣,問題在於當該方向上沒有其他節點時,您的代碼不會停止向左遍歷。 解決方法很簡單:

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

typedef struct node
{
    int data;
    struct node *llink;
    struct node *rlink;
} Node;

typedef struct Stack
{
    Node *a[10];
    int top;
} stack;

static
void push(stack *s, Node *root)
{
    if (s->top == 9)
        printf("FULL\n");
    else
    {
        s->top++;
        s->a[s->top] = root;
    }
}

static
Node *pop(stack *s)
{
    if (s->top == -1)
        printf("Empty\n");
    return s->a[s->top--];
}

static
void inorder(Node *root)
{
    stack s;
    s.top = -1;
    int flag = 1;
    while (flag)
    {
        //printf("I: %p\n", (void *)root);
        if (s.top != 9 && root != 0)
        {
            push(&s, root);
            root = root->llink;
        }
        else
        {
            if (s.top != -1)
            {
                root = pop(&s);
                printf(" %d", root->data);
                root = root->rlink;
            }
            else
                flag = 0;
        }
    }
}

static
void inor(Node *root)
{
    if (root != NULL)
    {
        inor(root->llink);
        printf(" %d", root->data);
        inor(root->rlink);
    }
}

static
Node *create(Node *root, int key)
{
    if (root == NULL)
    {
        root = (Node *)malloc(sizeof(Node));
        root->data = key;
        root->rlink = root->llink = NULL;
    }
    else
    {
        if (key > root->data)
        {
            root->rlink = create(root->rlink, key);
        }
        else if (key < root->data)
        {
            root->llink = create(root->llink, key);
        }
    }
    return root;
}

int main(void)
{
    int nodes[] = { 37, 2, 19, 9, 7, 41 };
    enum { NUM_NODES = sizeof(nodes) / sizeof(nodes[0]) };
    Node *h = NULL;
    h = create(h, 5);
    h = create(h, 1);
    h = create(h, 3);
    h = create(h, 8);
    h = create(h, 12);
    h = create(h, 51);
    printf("Recursive:\n");
    inor(h);
    putchar('\n');
    printf("Iterative:\n");
    inorder(h);
    putchar('\n');

    for (int i = 0; i < NUM_NODES; i++)
    {
        h = create(h, nodes[i]);
        printf("Iterative:\n");
        inorder(h);
        putchar('\n');
    }
}

我在函數上使用static ,因為我的默認編譯器選項要求在使用前聲明或定義函數,並且只能定義static函數而無需預先聲明:

gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition it37.c -o it37

您可以自行決定是否對自己很重要(但是我注意到,除了該文件之外,沒有文件需要訪問這些功能,因此“信息隱藏”建議這些功能應該是static )。

樣本輸出:

Recursive:
 1 3 5 8 12 51
Iterative:
 1 3 5 8 12 51
Iterative:
 1 3 5 8 12 37 51
Iterative:
 1 2 3 5 8 12 37 51
Iterative:
 1 2 3 5 8 12 19 37 51
Iterative:
 1 2 3 5 8 9 12 19 37 51
Iterative:
 1 2 3 5 7 8 9 12 19 37 51
Iterative:
 1 2 3 5 7 8 9 12 19 37 41 51

如上面的注釋所述,代碼中的“根”總是得到左節點的分配地址,當到達葉節點時,其中具有“ NULL”值,並且您無法訪問null,這就是代碼失敗的原因,並且會給您細分錯誤。

無論如何,這是我的代碼來解決您的錯誤

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


typedef struct node
{
    int data;
    struct node *llink;
    struct node *rlink;
}Node;


typedef struct Stack
{
    Node *a[10];
    int top;
}stack;

void push(stack *s,Node *root);
Node *pop(stack *s);
void inorder(Node *root);



void push(stack *s,Node *root)
{
    if(s->top==9)
    {
        printf("FULL");
    }
    else
    {
        s->top++;
        s->a[s->top]=root;
    }
}


Node *pop(stack *s)
{
    if(s->top==-1)
    {
        printf("Empty");
        return  NULL;
    }

    return s->a[s->top--];
}
void inorder(Node *root)
{
    stack *s;// took it as a pointer so that i could use it easily
    s=(stack *)malloc(sizeof(stack));
    s->top=-1;//initialized to -1 because we increment top then insert at location indicated by top
    int flag=1;
    bool traverse_left=true;

    while(flag)
    {
        if( root->llink!=NULL && traverse_left )//if left link available go left
        {
            push(s,root);
            root=root->llink;
        }
        else if((root->llink==NULL&&root->rlink!=NULL)||(root->llink!=NULL && !traverse_left))
        {
            printf("%d  ",root->data);
            root=root->rlink;
            traverse_left=true;
        }
        else if(root->llink==NULL&&root->rlink==NULL)
        {
            printf("%d  ",root->data);
            if(root->llink==NULL&&root->rlink==NULL&&s->top==-1)
            {
                flag=0;
            }
            else
            {
                root=pop(s);
            }
            traverse_left=false;
        }


    }
}


void inor(Node *root)
{
    if(root!=NULL)
    {
        inor(root->llink);
        printf("%d",root->data);
        inor(root->rlink);
    }
}

Node *create(Node *root,int key)
{
    if(root==NULL)
    {
        root=(Node *)malloc(sizeof(Node));
        root->data=key;
        root->rlink=root->llink=NULL;
    }

    else
    {
        if(key>root->data)
        {
            root->rlink=create(root->rlink,key);
        }
        else if(key<root->data)
        {
            root->llink=create(root->llink,key);
        }
    }

return root;
}
int main()
{
    Node *h=NULL;

    h=create(h,5);
    h=create(h,1);
    h=create(h,3);
    h=create(h,8);
    h=create(h,12);
    h=create(h,51);

    inorder(h);
    //inor(h);
}
  • 在該程序中,每當我們向左節點移動時,我都會將該節點放在堆棧中,然后再移至左節點

  • 當遍歷堆棧是否包含左節點時,這意味着我們已經遍歷了它的左樹,所以我將其彈出並開始遍歷它的右子樹

  • 如果節點的左右指針為空,則從堆棧中彈出該節點,然后開始遍歷該節點的右子樹

如果您對此答案有任何疑問,請發表評論。

順序遍歷:左,父,右

使用堆棧進行迭代遍歷的關鍵思想是:

  1. 向左走(也推入堆棧),直到找到null為止。

  2. 運行while循環,直到堆棧為空。 每次彈出頂部元素時,將其添加到結果列表中。 然后,如果存在正確的子代,請轉到正確的子代(也推入堆棧),然后向左(也推入堆棧)直到找到null 因此,基本上,第1步的代碼將復制到while循環內。

代碼如下:

class Node {
    int key;
    Node left, right;

    public Node() {}

    public Node(int key) {
        this.key = key;
    }
}
public List<Integer> inOrderIterative() {
    List<Integer> list = new ArrayList<>();
    Stack<Node> nodeStack = new Stack<>();
    Node current = root;
    nodeStack.push(current);
    while (null != current.left) {
        current = current.left;
        nodeStack.push(current);
    }

    while(!nodeStack.empty()) {
        current = nodeStack.pop();
        list.add(current.key);

        if (null != current.right) {
            current = current.right;
            nodeStack.push(current);
            while (null != current.left) {
                current = current.left;
                nodeStack.push(current);
            }
        }
    }

    return list;
}

暫無
暫無

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

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