C++ BST的实现中, 内存分配的情况

关于BST的实现代码, 参见上一个文章, 这里只是贴出代码:

// Binary Search Tree - Implemenation in C++
// Simple program to create a BST of integers and search an element in it
#include<iostream>
using namespace std;
//Definition of Node for Binary search tree
struct BstNode {
	int data;
	BstNode* left;
	BstNode* right;
};

// Function to create a new Node in heap
BstNode* GetNewNode(int data) {
	BstNode* newNode = new BstNode();
	newNode->data = data;
	newNode->left = newNode->right = NULL;
	return newNode;
}

// To insert data in BST, returns address of root node
BstNode* Insert(BstNode* root,int data) {
	if(root == NULL) { // empty tree
		root = GetNewNode(data);
	}
	// if data to be inserted is lesser, insert in left subtree.
	else if(data <= root->data) {
		root->left = Insert(root->left,data);
	}
	// else, insert in right subtree.
	else {
		root->right = Insert(root->right,data);
	}
	return root; // 若无, 则回传为void, 由于root的scope 我local variable, 所以。。。
}
//To search an element in BST, returns true if element is found
bool Search(BstNode* root,int data) {
	if(root == NULL) {
		return false;
	}
	else if(root->data == data) {
		return true;
	}
	else if(data <= root->data) {
		return Search(root->left,data);
	}
	else {
		return Search(root->right,data);
	}
}
int main() {
	BstNode* root = NULL;  // Creating an empty tree, root is to store the address of the root node
	/*Code to test the logic*/
	root = Insert(root,15);
	root = Insert(root,10);
	root = Insert(root,20);
	root = Insert(root,25);
	root = Insert(root,8);
	root = Insert(root,12);
	// Ask user to enter a number.
	int number;
	cout<<"Enter number be searched\n";
	cin>>number;
	//If number is found, print "FOUND"
	if(Search(root,number) == true) cout<<"Found\n";
	else cout<<"Not Found\n";

	return 0;
}


主要参考上面的主程序。 一个而言, 一个C++ 程序编译时, 在内存的分配情况如下图所示:

程序占用的内存可以分为四个区域段(segment)。

一个segment 称为代码段(text segment), 这个区域用于存储程序的指令(instructions in the program)。 这些instructions 将会被编译为machine language.

一个segement 称为global segment, 用于存储程序中的全局变量(global variables)。  这些变量对于所有的函数都可以access的。

一个segment被称为stack(注意和数据结构中的stack区别开),   这个区域主要在函数调用的时候, 用于存储函数内部定义的局部变量等等。 一个函数可以认为一个stack fram, 函数调用就是层层累计。

上述三个代码段均是编译时分配固定的内存大小。一旦编译完成, 就不再改变。 然而heap 却是dynamic的。

最后一个segment是heap, 主要是用于动态态分配(用new 算子分配)的变量内存区域, heap 又被称为free store。 不用的空间要学会delete掉, 以避免消耗内存, 造成么memory leak。 这个是动态内存区域大小, 也就是说根据我们的需要可以增长或者消减内存大小(can grow  and shrink)。

下面用下图表明程序在运行的时候, stack和heap的情况:

 首先第一步, 运行main函数, 一旦运行函数, 编译器就会为该函数在stack中分配一定的内存空间(stack frame), 用于存储函数的局部变量等。

(1)运行main函数的第一句, 分配情况如下



(2)运行main函数的第二句: root = Insert(root, 15), 出现函数的调用,为Insert函数在stack 中分配一个stack frame, 堆在main() 的stack frame 之上(就像堆卡片一样)。

接下来, 根据条件, 运行到root = getNewNode(data) 函数, 再次分配getNewNode 的stack frame, 保存下Insert 函数中断的位置。

在getNewNode 中有两个局部变量:

 

在这个函数中, 我们使用了new operator 在heap中申请了存放BstNode 的内存空间, 该创建的内存地址存放在newNode 指针中:

然后, 我们利用newNode 指针设定节点3个fields 的值:

接下来, 函数getNewNode 会返回该创建的新的节点, 于是这个stack fram就从Insert函数的stack frame上拿走,并将root的地址设为200 , 如下:

 

 

接下来, Insert函数沿着之前保存下来的断点继续运行, 就return root, 同理, 于是返回到了主函数的stack frame中:

于是, 沿着main 函数保存下来的断点执行。 执行下一步的赋值操作: root = Insert(root, 15), 由于Insert函数在上一步返回了200, 所以最终完成这一个语句, 即root = 200, root 存放着BSt树(虽然此时只有一个节点):

 

接下来, 运行main 函数的下一句: root = Insert(root, 10); 运行的过程如下:

step1:

  

   step2: 由于此时root 不是NULL, 故而, 进入 else if 语句判断, 10 < 15, 所以满足这个条件:

接下来, 就发生了递归调用(这和一般的函数调用没啥大的区别), 分配stack frame:

 

接下来, 在最上面的那个函数中, 由于root 为0, 所以会调用getNewNode函数创建新的节点:

最终返回150, 赋给下一层调用这个函数的Insert的root 变量, 于是有:

接下来, 我们返回root(即150), 到下一frame对应的Insert函数的中断出的位置处:

接下来, 在这个stack frame中, 我们运行: root -> left = 150(设定root 的left的field的指针内容), 接下来, 返回root(200), 赋值给root, 这样, 我们就将这两个节点连接起来了:

 

接下来, main函数中, 执行下一语句: root = Insert(root, 20)。 

这与上面分析的步骤类似, 不再赘述。 只不过此时检点建立在右子树上。 最终效果如下:

 

接下来, 再次回到main函数中, 运行下一语句: root = Insert(root, 25), 如下:

 

此时, 第一步, main 函数中调用Insert函数:

由于root 不是NULL, 继续递归调用Insert:

由于传进该层Insert函数的root 不是Null, 继续判断, 递归调用:

继续递归调用, 会出现NULL, 运行getNewNode 函数创建新的节点(假如在heap的地址为100)之后, 返回100给下一层的root, 如下图:

此时, 返回到这一层的函数的断点处运行, 相当于root ->  right = 100, 设定完之后, 相当于链接起来, 然后 return root(即300), 返回下一stack frame:

此时, 如下: root -> lright= 200,

最终, 得到如下:

剩下的分析就简单了不再赘述。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值