第十三章 搜索

		void insert(int t)
		{
			head = iinsert(head, t);
		}
		
		node *iinsert(node *p, int t)
		{
			if (p->val < t)						//or if (!p) return p = new node(t, 0); //退出说明不满足if条件,继续后面的执行,而退出可能是因为p->val == t或者p->val > t,因此继续进行判断,从而确定是否要创建新节点
				p->next = iinsert(p->next, t);
			else if (p->val > t)				//a sentinel 
			{
				p = new node(t, p);
				n++;
			}
			return p;	//直到return 时,真正的递归才结束,但是递归不变性,可以将递归看作之前的循环已经结束。
		}
		
		node *iinsert2(node *p, int t)
		{
			while (p->val < t)					//interrupt because of sentinel or while(p && p->val < t)
				p = p->next;
			if (p->val > t)						//p->val == t, return p
			{
				p = new node(t, p);
				n++;
			}
			return p;
		}
		
		void insert2(int t)
		{
			node **p;
			for (p = &head; (*p)->val < t; p = &((*p)->next))
				;
			if ((*p)->val == t)
				return;
			*p = new node(t, p);
			n++;
		}

以上是链表的插入操作;

void insert(int t)
		{
			node = iinsert(root, t);
		}
		node *iinsert(node *p, int t)
		{
			if (p == 0)
			{
				p = new node(t);
				n++;
			}
			if (p->val < t)
				p->left = iinsert(p->left, t);//递归结束,可能p->val==t, 可能p->val > p, 进而进入判断, 不是尾递归,因此顺序执行后边命令,                                                            //事实上前边的判断放置在后边更好,表明顺序执行,这样有助于理解
			if (p->val > t)
				p->right = iinsert(p->right, t);
			if (p->val == t)
				return p;
		}

以上是二叉树的插入操作。


1 进一步理解哨兵的使用:减少if的判断 , 在数组set, 链表set, 以及箱set的链表实现中,都在insert的操作中添加了哨兵,目的是与之前常规元素的判断一致,而二叉树的哨兵添加,则没有实际意义,因为它的插入判断,没有一致性。

2进一步理解递归,类似与循环不变性,递归有递归不变性,其不变性就是它满足的递归的条件,退出递归,说明不满足递归的不变性

因此,递归可以理解为循环,循环条件就是进入递归的条件,即从if语句开始,所有的语句重复执行,若是尾递归,则“循环”结束后,整个函数调用结束,若不是尾递归,则循环结束后,将会有返回值返回给调用者


Guess you like

Origin blog.csdn.net/juttajry/article/details/51245085