閱讀581 返回首頁    go 阿裏雲 go 技術社區[雲棲]


網絡子係統40_inet_peer平衡二叉樹的插入

                                

                  

                            

                 


//	遍曆二叉樹路徑
//	宏的主要任務:	
//		1.遍曆到達目標節點的路徑
//		2.將路徑上經過的節點保存在stack中
//		3.棧頂為peer_avl_empty
//		4.stackptr指向下一個空閑的位置
1.2 #define lookup(_daddr,_stack) 				\
({								\
	struct inet_peer *u, **v;				\
	if (_stack != NULL) {					\
		stackptr = _stack;//棧指針指向棧底		\
		*stackptr++ = &peer_root;//棧底為root,移動棧指針	\
	}							\
	for (u = peer_root; u != peer_avl_empty; ) {		\
		if (_daddr == u->v4daddr)			\
			break;					\
		if ((__force __u32)_daddr < (__force __u32)u->v4daddr)	\
			v = &u->avl_left;			\
		else						\
			v = &u->avl_right;			\
		if (_stack != NULL)				\
			*stackptr++ = v;			\
		u = *v;						\
	}							\
	u;							\
})

//	插入平衡二叉樹
//	注:新節點的初始化為1
#define link_to_pool(n)						\
do {								\
	n->avl_height = 1;			\
	n->avl_left = peer_avl_empty;	//左右均為empty		\
	n->avl_right = peer_avl_empty;				\
	**--stackptr = n;	//通過將節點壓入棧頂,完成插入操作	\
	peer_avl_rebalance(stack, stackptr);//調整二叉樹平衡			\
} while(0)

//	平衡二叉樹
//	參數:
//		stack,尋找目標節點時路徑上經過的所有節點
//		stackend,棧頂指針

1.3 static void peer_avl_rebalance(struct inet_peer **stack[],
		struct inet_peer ***stackend)
{
	struct inet_peer **nodep, *node, *l, *r;
	int lh, rh;

	while (stackend > stack) {//stackend指向的節點非根節點
		nodep = *--stackend;//nodep為指向要插入節點的父節點的指針
		node = *nodep;//父節點的指針
		l = node->avl_left;//父節點的左孩子
		r = node->avl_right;//右孩子
		lh = node_height(l);//高度
		rh = node_height(r);
		if (lh > rh + 1) { //根平衡因子變為2
			struct inet_peer *ll, *lr, *lrl, *lrr;
			int lrh;
			ll = l->avl_left;//根的左孩子的左孩子
			lr = l->avl_right;//根的左孩子的右孩子
			lrh = node_height(lr);//左孩子的右孩子的高度
			if (lrh <= node_height(ll)) {	//並且是在左孩子的左子樹插入節點,RR,情況1.1
				node->avl_left = lr;	/* lr: RH or RH+1 */
				node->avl_right = r;	/* r: RH */
				node->avl_height = lrh + 1; /* RH+1 or RH+2 */
				l->avl_left = ll;	/* ll: RH+1 */
				l->avl_right = node;	/* node: RH+1 or RH+2 */
				l->avl_height = node->avl_height + 1;
				*nodep = l;	//左孩子成為
			} else { //並且是在左孩子的右子樹插入節點,LL,RR,情況1.2
				lrl = lr->avl_left;	/* lrl: RH or RH-1 */
				lrr = lr->avl_right;	/* lrr: RH or RH-1 */
				node->avl_left = lrr;	/* lrr: RH or RH-1 */
				node->avl_right = r;	/* r: RH */
				node->avl_height = rh + 1; /* node: RH+1 */
				l->avl_left = ll;	/* ll: RH */
				l->avl_right = lrl;	/* lrl: RH or RH-1 */
				l->avl_height = rh + 1;	/* l: RH+1 */
				lr->avl_left = l;	/* l: RH+1 */
				lr->avl_right = node;	/* node: RH+1 */
				lr->avl_height = rh + 2;
				*nodep = lr;	//左孩子的右子樹根成為當前的根節點
			}
		} else if (rh > lh + 1) { //根平衡因子變為-2
			struct inet_peer *rr, *rl, *rlr, *rll;
			int rlh;
			rr = r->avl_right;
			rl = r->avl_left;
			rlh = node_height(rl);
			if (rlh <= node_height(rr)) {	//在右孩子的右子樹上插入節點,LL,情況1.3
				node->avl_right = rl;	/* rl: LH or LH+1 */
				node->avl_left = l;	/* l: LH */
				node->avl_height = rlh + 1; /* LH+1 or LH+2 */
				r->avl_right = rr;	/* rr: LH+1 */
				r->avl_left = node;	/* node: LH+1 or LH+2 */
				r->avl_height = node->avl_height + 1;
				*nodep = r;//右孩子作為根節點
			} else { //在右孩子的左子樹上插入節點,RR,LL,情況1.4
				rlr = rl->avl_right;	/* rlr: LH or LH-1 */
				rll = rl->avl_left;	/* rll: LH or LH-1 */
				node->avl_right = rll;	/* rll: LH or LH-1 */
				node->avl_left = l;	/* l: LH */
				node->avl_height = lh + 1; /* node: LH+1 */
				r->avl_right = rr;	/* rr: LH */
				r->avl_left = rlr;	/* rlr: LH or LH-1 */
				r->avl_height = lh + 1;	/* r: LH+1 */
				rl->avl_right = r;	/* r: LH+1 */
				rl->avl_left = node;	/* node: LH+1 */
				rl->avl_height = lh + 2;
				*nodep = rl;	//右孩子的左子樹根作為當前的根節點
			}
		} else {//平衡因子為0,1,-1
			node->avl_height = (lh > rh ? lh : rh) + 1;
		}
	}
}


最後更新:2017-04-03 14:53:37

  上一篇:go 萊斯信道matlab建模
  下一篇:go matlab中函數的句柄