數據結構(C語言版)第五章:樹

5.2 二叉樹 算法

咱們寫一個二叉樹,它支持樹的插入,刪除,查詢和遍歷,並且左子樹的數據都小於右子樹的數據(PS:樹實際上很難的,想深刻了解的話,能夠去看看<算法導論>,什麼紅黑樹啊,B樹啊什麼的,反正我沒看懂就是了--估計是我太菜了^_^): 數據結構

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct TREE{
	int						data;
	struct TREE			*leftChild;
	struct TREE			*rightChild;
}Tree;

void insertTree( Tree *tree, int data );
void deleteTree( Tree *tree, int data );
int searchTree( Tree *tree, int data );
void showTree( Tree *tree );

int main( void )
{
	Tree *tree = ( Tree * )malloc( sizeof( Tree ) );
	tree->leftChild = tree->rightChild = NULL;

	insertTree( tree, 5 );
	insertTree( tree, 3 );
	insertTree( tree, 2 );
	insertTree( tree, 4 );
	insertTree( tree, 8 );
	insertTree( tree, 7 );
	insertTree( tree, 9 );
	insertTree( tree, 6 );

	showTree( tree->leftChild );

	deleteTree( tree, 3 );
	deleteTree( tree, 5 );
	deleteTree( tree, 6 );

	printf("\n");
	showTree( tree->leftChild );

	printf("\n");
	if ( searchTree( tree, 8 ) ){
		printf("8 in the tree\n");
	}
	else{
		printf("8 not in the tree\n");
	}

	if ( searchTree( tree, 13 ) ){
		printf("13 in the tree\n");
	}
	else{
		printf("13 not in the tree\n");
	}

	return 0;
}

void insertTree( Tree *tree, int data )
{
	Tree *newTree = ( Tree * )malloc( sizeof( Tree ) );
	newTree->leftChild = newTree->rightChild = NULL;
	newTree->data = data;

	if ( ( NULL == tree->leftChild ) && ( NULL == tree->rightChild ) ){
		tree->leftChild = newTree;
	}
	else{
		tree = tree->leftChild;
		while ( NULL != tree ){
			if ( data == tree->data ){
				return;	
			}
			else if ( data < tree->data ){
				if ( NULL == tree->leftChild ){
					tree->leftChild = newTree;
					return;
				}
				tree = tree->leftChild;
			}
			else{
				if ( NULL == tree->rightChild ){
					tree->rightChild = newTree;
					return;
				}
				tree = tree->rightChild;
			}
		}
	}
}

/*
找到被刪除節點的右子樹的最小節點,刪除最小節點而且將其值賦給被刪除的節點
*/
void deleteTree( Tree *tree, int data )
{
	Tree *prevTree = ( Tree * )malloc( sizeof( Tree ) );		//指向刪除節點的前一個節點
	Tree *tempTree = ( Tree * )malloc( sizeof( Tree ) );		//處理被刪除的節點擁有左右樹的特殊狀況
	prevTree = tree;
	tree = tree->leftChild;

	while ( tree ){
		if ( data < tree->data ){
			prevTree = tree;
			tree = tree->leftChild;
		}
		else if ( data > tree->data ){
			prevTree = tree;
			tree = tree->rightChild;
		}
		else{
			//刪除節點的左子樹爲空,則直接用右子樹替換該節點
			if ( NULL == tree->leftChild ){
				if ( data == prevTree->leftChild->data ){
					prevTree->leftChild = prevTree->leftChild->rightChild;
				}
				else{
					prevTree->rightChild = prevTree->rightChild->rightChild;
				}
			}
			else if ( NULL == tree->rightChild ){		//刪除節點的右子樹爲空,則直接用左子樹替換該節點
				if ( data == prevTree->leftChild->data ){
					prevTree->leftChild = prevTree->leftChild->leftChild;
				}
				else{
					prevTree->rightChild = prevTree->rightChild->leftChild;
				}
			}
			else{
				tempTree = tree;		//保存右子樹中最小節點的前節點
				tree = tree->rightChild;
				while ( tree->leftChild ){			//找到最小節點
					tempTree = tree;
					tree = tree->leftChild;
				}
				//替換數據
				if ( data == prevTree->leftChild->data ){
					prevTree->leftChild->data = tree->data;
				}
				else{
					prevTree->rightChild->data = tree->data;
				}

				//刪除最小節點
				if ( tempTree->leftChild->data == tree->data ){
					tempTree->leftChild = tree->rightChild;
				}
				else{
					tempTree->rightChild = tree->rightChild;
				}
			}
			break;
		}
	}
}
int searchTree( Tree *tree, int data )
{
	tree = tree->leftChild;
	while ( tree ){
		if ( data == tree->data ){
			return 1;
		}
		else if ( data < tree->data ){
			tree = tree->leftChild;
		}
		else{
			tree = tree->rightChild;
		}
	}

	return 0;
}
void showTree( Tree *tree )
{
	if ( tree ){
		printf("%d ", tree->data );
		showTree( tree->leftChild );
		showTree( tree->rightChild );
	}
}



程序輸出:

發現效率有點低@_@ 學習

二叉樹有四種遍歷方式:前序遍歷,中序遍歷,後序遍歷,層序遍歷.其中,層序遍歷比較難.因此嘗試寫下代碼看看: .net

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_SIZE 100
typedef struct TREE{
	int						data;
	struct TREE			*leftChild;
	struct TREE			*rightChild;
}Tree;

Tree *stack[ MAX_SIZE ];
int top = 0;
int rear = 0;

void insertTree( Tree *tree, int data );
void showTree( Tree *tree );

int main( void )
{
	Tree *tree = ( Tree * )malloc( sizeof( Tree ) );
	tree->leftChild = tree->rightChild = NULL;

	insertTree( tree, 5 );
	insertTree( tree, 3 );
	insertTree( tree, 2 );
	insertTree( tree, 4 );
	insertTree( tree, 8 );
	insertTree( tree, 7 );
	insertTree( tree, 9 );
	insertTree( tree, 6 );

	showTree( tree->leftChild );

	

	return 0;
}

void insertTree( Tree *tree, int data )
{
	Tree *newTree = ( Tree * )malloc( sizeof( Tree ) );
	newTree->leftChild = newTree->rightChild = NULL;
	newTree->data = data;

	if ( ( NULL == tree->leftChild ) && ( NULL == tree->rightChild ) ){
		tree->leftChild = newTree;
	}
	else{
		tree = tree->leftChild;
		while ( NULL != tree ){
			if ( data == tree->data ){
				return;	
			}
			else if ( data < tree->data ){
				if ( NULL == tree->leftChild ){
					tree->leftChild = newTree;
					return;
				}
				tree = tree->leftChild;
			}
			else{
				if ( NULL == tree->rightChild ){
					tree->rightChild = newTree;
					return;
				}
				tree = tree->rightChild;
			}
		}
	}
}

void showTree( Tree *tree )
{
	stack[ rear++ ] = tree;
	while ( 1 ){
		tree = stack[ top++ ];
		if ( tree ){
			printf("%d ", tree->data );
			if ( tree->leftChild ){
				stack[ rear++ ] = tree->leftChild;
			}
			if ( tree->rightChild ){
				stack[ rear++ ] = tree->rightChild;
			}
		}
		else{
			break;
		}
	}
}



實際上用到的是隊列的思想,而不是堆棧的思想.程序輸出:


5.4 二叉樹的其餘操做 指針

1. 二叉樹的複製 code

直接將頭指針賦值便可. blog

2. 判斷二叉樹的等價性 排序

須要用到遞歸,代碼相似以下: 遞歸

int equal(tree_pointer first, tree_pointer second )
{
    return ((!first && !second)||(first && second && 
              (first->data == second->data)) && 
               equal(first->left_child, second->left_child) &&
               equal(first->right_child, second->right_child))
}



3. 交換左右子樹
void swapLeftRight( Tree *tree )
{
	if ( tree ){
		Tree *tempTree = ( Tree * )malloc( sizeof( Tree ) );
		tempTree = tree->leftChild;
		tree->leftChild = tree->rightChild;
		tree->rightChild = tempTree;
		swapLeftRight( tree->leftChild );
		swapLeftRight( tree->rightChild );
	}
}


5.5 線索二叉樹 隊列

線索二叉樹經過增長數據結構而簡化遍歷,這種想法是否可取得進一步討論.


5.6 堆

1. 最大樹是指在樹中,一個結點有兒子結點,其關鍵字都不小於兒子結點的關鍵字值.最大堆是一棵徹底二叉樹,也是一棵最大樹.

2. 最小數是指在樹中,一個結點有兒子結點,其關鍵字都不大於兒子結點的關鍵字值.最小堆是一棵徹底二叉樹,也是一棵最小數.

http://my.oschina.net/voler/blog/167320

以前學習算法導論的時候,堆排序作了很詳細的筆記.因此這裏就再也不重複了(不過有點忘記了.仍是得找段時間好好研究一下算法導論).

5.7 二叉搜索樹

這篇文章剛開始的時候就用一個程序開頭,就是二叉搜索樹的增刪查.故再也不重複.

相關文章
相關標籤/搜索