快速排序和二叉树遍历的非递归算法

快速排序和二叉树遍历的递归算法大家都很熟悉,但非递归算法比较复杂。

快速排序非递归算法:

int partition(int a[],int low,int high)
{
    if(a==NULL)
        exit(1);
    int pvot=a[low];
    while(low<high)
    {
        while(low<high&&a[high]>=pvot)--high;
        a[low]=a[high];
        while(low<high&&a[low]<=pvot)++low;
        a[high]=a[low]
    }
    a[low]=pvot;
    return low;
}
void QuickSort(int a[],int low,int high)
{
    stack<int>st;
    if(low<high)
    {
        int mid=partition(a,low,high);
        if(low<mid-1)
        {
            st.push(low);
            st.push(mid-1);
        }
        if(mid+1<high)
        {
            st.push(mid+1);
            st.push(high);
        }
    }
    while(!st.empty())
    {
        high=st.top();
        st.pop();
        low=st.top();
        st.pop();
        int mid=partition(a,low,high);
        if(low<mid-1)
        {
            st.push(low);
            st.push(mid-1);
        }
        if(mid+1<high)
        {
            st.push(mid+1);
            st.push(high);
        }
    }
}

二叉树的非递归遍历

1.前序
根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。因此其处理过程如下:

对于任一结点P:

1)访问结点P,并将结点P入栈;

2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;

3)直到P为NULL并且栈为空,则遍历结束。

void preOrder2(BinTree *root)     //非递归前序遍历 
{
    stack<BinTree*> s;
    BinTree *p=root;
    while(p!=NULL||!s.empty())
    {
        while(p!=NULL)
        {
            cout<<p->data<<" ";
            s.push(p);
            p=p->lchild;
        }
        if(!s.empty())
        {
            p=s.top();
            s.pop();
            p=p->rchild;
        }
    }
}

2.中序
根据中序遍历的顺序,对于任一结点,优先访问其左孩子,而左孩子结点又可以看做一根结点,然后继续访问其左孩子结点,直到遇到左孩子结点为空的结点才进行访问,然后按相同的规则访问其右子树。因此其处理过程如下:

对于任一结点P,

1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;

2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;

3)直到P为NULL并且栈为空则遍历结束

void inOrder2(BinTree *root)      //非递归中序遍历
{
    stack<BinTree*> s;
    BinTree *p=root;
    while(p!=NULL||!s.empty())
    {
        while(p!=NULL)
        {
            s.push(p);
            p=p->lchild;
        }
        if(!s.empty())
        {
            p=s.top();
            cout<<p->data<<" ";
            s.pop();
            p=p->rchild;
        }
    }    
} 

3.后序
后序遍历的非递归实现是三种遍历方式中最难的一种。因为在后序遍历中,要保证左孩子和右孩子都已被访问并且左孩子在右孩子前访问才能访问根结点,这就为流程的控制带来了难题。

void postOrder2(BNode* root)   //非递归后序遍历
{
    if(!root)
        return;
    stack<BNode*>st;
    BNode* p=root;
    BNode* r=nullptr;
    while(p||!st.empty())
    {
        if(p)
        {
            st.push(p);
            p=p->left;
        }
        else
        {
            p=st.top();
            if(p->right&&p->right!=r)
            {
                p=p->right;
                st.push(p);
                p=p->left;
            }
            else
            {
                p=st.top();
                st.pop();
                cout<<p->key<<" ";
                r=p;
                p=nullptr;
            }
        }
    }
}

你可能感兴趣的:(二叉树,快速排序)