用栈实现二叉树的非递归遍历与非递归实现快速排序的联系

目录

一、栈与递归的联系

二、二叉树的非递归遍历(前序)

1.  递归解决前序遍历的过程

2. 由递归复刻到非递归

3. 核心代码:144. 二叉树的前序遍历 - 力扣(Leetcode)

三、非递归实现快速排序

一、栈与递归的联系

在调用函数时内存中的栈会为函数开辟函数栈帧,由于栈顶为低地址,栈底为高地址,具体为栈指针寄存器%rsp减去一定大小的值(subq),函数结束再通过addq指令释放函数所开辟的空间,深入理解函数调用的底层实现很有利于我们理解如何用数据结构的栈来模拟递归过程。

递归实际上就是在栈区开辟函数栈帧,同一层递归在栈区上的空间是大概一致的。

所以我们可以用栈这一数据结构来实现一些规律较为明显的递归,同时需要注意栈先进后出的规则。

二、二叉树的非递归遍历(前序)

1.  递归解决前序遍历的过程

① 返回条件:当节点为空指针时返回;

② 处理顺序:前序遍历为中、左、右,所以先处理根节点,再依次递归左右节点;

2. 由递归复刻到非递归


① 返回条件:由与节点为空时返回,所以空节点没有必要加入栈中;最终栈里没有数据,即类似于%rsp回到函数调用前的位置,此时递归结束,循环也结束;

② 处理顺序:首先处理根节点,由于先进后出,先将右节点加入栈,再将左节点加入栈,接下来的下一次循环取栈顶元素,对应于进入下层递归;

3. 核心代码:144. 二叉树的前序遍历 - 力扣(Leetcode)

C语言:

int* preorderTraversal(struct TreeNode* root, int* returnSize){
    struct TreeNode* st[100];   
    int stTop = 0;
    int* res = (int*)malloc(sizeof(int)*100);
    int resTop = 0;
    
    st[stTop++] = root; 
    while(stTop){
        struct TreeNode* node = st[--stTop];
        if(node == NULL){
            continue;
        }
        res[resTop++] = node -> val;    //中
        st[stTop++] = node -> right;    //左
        st[stTop++] = node -> left;     //右
    }
    *returnSize = resTop;
    return res;
}

C++:

class Solution {
public:
    vector preorderTraversal(TreeNode* root) {
        vector res;
        if (root == nullptr) return res;

        stack st;
        st.push(root);
        while (!st.empty()) {
            TreeNode* tmp = st.top();
            st.pop();
            res.push_back(tmp->val);

            if (tmp->right != nullptr) st.push(tmp->right);
            if (tmp->left != nullptr) st.push(tmp->left);
        }

        return res;
    }
};

三、非递归实现快速排序

快速排序的三种方法以及递归与非递归在之前的文章中有讲解过,有兴趣的可以去简单阅读一下:

(2条消息) 【数据结构(三)】用C语言实现希尔、堆、快排、归并、三数找中、小区间优化——肝n小时图解进阶排序算法,不信你学不会_算法逻辑gif怎么制作_Dusong_的博客-CSDN博客

快速排序与二叉树的前序遍历有着非常大的相似之处,快速排序是将基准值排到最终位置,再递归左右区间,而二叉树是处理根节点再递归左右子树:

用栈实现二叉树的非递归遍历与非递归实现快速排序的联系_第1张图片

 根据这个相似之处,我们可以照搬非递归遍历二叉树的代码模板实现非递归快速排序:

C语言:

void QuickSortNonR(int* a, int left, int right) {
	int st[10000];
	int stTop = 0;
	st[stTop++] = right;
	st[stTop++] = left;

	while (stTop) {
		int begin = st[--stTop], end = st[--stTop];
		left = begin, right = end;   //保存区间的头尾的位置
		int keyi = begin;   

		while (begin < end) {
			while (begin < end && a[end] >= a[keyi]) end--;
			while (begin < end && a[begin] <= a[keyi]) begin++;
			 
			Swap(&a[begin], &a[end]);   
		}
		                                        
		Swap(&a[keyi], &a[begin]);   //“处理根节点”

		if (right - (begin + 1) > 0) {    //“递归左区间”
			st[stTop++] = right;
			st[stTop++] = begin + 1;
		}
		if ((begin - 1) - left > 0) {     //“递归右区间”
			st[stTop++] = begin - 1;
			st[stTop++] = left;
		}
	}
}

C++:

void QuickSortNonR(int* a, int left, int right) {
	stack st;
	st.push(right);
	st.push(left);

	while (!st.empty()) {
		int begin = st.top();
		st.pop();
		int end = st.top();
		st.pop();
		left = begin, right = end;   //保存区间的头尾的位置
		int keyi = begin;   

		while (begin < end) {
			while (begin < end && a[end] >= a[keyi]) end--;
			while (begin < end && a[begin] <= a[keyi]) begin++;
			 
			Swap(&a[begin], &a[end]);   
		}
		                                        
		Swap(&a[keyi], &a[begin]);   //“处理根节点”

		if (right - (begin + 1) > 0) {    //“递归左区间”
			st.push(right);
			st.push(begin + 1);
		}
		if ((begin - 1) - left > 0) {     //“递归右区间”
			st.push(begin - 1);
			st.push(left);
		}
	}
}

你可能感兴趣的:(算法,数据结构,算法,数据结构)