查找的相關操作總結

操作包含

  1. 遞歸折半查找
  2. 非遞歸折半查找
  3. 二叉排序樹的建立、查找、刪除、插入
  4. 哈希表的建立和輸出
  5. 判斷一個二叉樹是不是平衡二叉樹

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

#define MAX_SIZE 100

int nums1[] = {5,7,3,2,9,4,8,1,10,6};

int nums2[] = {1,2,3,4,5,6,7,8,9,10};

int nums3[] = {51,24,23,4,57,69,70,18,9,10};

typedef struct BiNode{
	int data;
	struct BiNode *lchild;
	struct BiNode *rchild;

}BiNode;

void printData(int i){
	printf("The index of the num is %d",i);
}

void printData2(int i){
	printf("%d ",i);
}

void printInfo(char *s){
	printf("%s",s);
}




//遞歸折半查找
int binSearch(int low,int high ,int i){

	if (low > high){
		return -1;
	}

	int mid = (low + high)/2;

	if (nums2[mid] < i){
		low = mid + 1;
		return binSearch(low,high,i);
	} else if (nums2[mid] > i){
		high = mid -1;
		return binSearch(low,high,i);
	}else {
		return mid;
	}

}
//非遞歸折半查找
//時間複雜度O(log2n)
void binSearch2(int i){
	int low = 0,high = 9;
	int mid;

	while(low <= high){

		mid = (low + high)/2;

		if (nums2[mid] < i){
			low = mid + 1;
			
		} else if (nums2[mid] > i){
			high = mid -1;
		}else {
			printData(mid);
			break;
		}
	}
}
/****************************************二叉排序樹的操作開始**********************************************/
BiNode* mallocNewNode(int data){
	BiNode * root ;
	root = (BiNode*)malloc(sizeof(BiNode));
	root->data = data;
	root->rchild = NULL;
	root->lchild = NULL;
	return root;
}

//創建二叉排序樹
BiNode* createBST(){
	int i = 1,data;
	int flag;
	BiNode * root ,*p,*pre;

	root = mallocNewNode(nums1[0]);
	p = root;

	for (i = 1; i< 10;i++){
		data = nums1[i];
		p = root;
		//直到p爲空爲止,這時證明p已經處於葉子結點。
		while(p != NULL){
			if (p->data < data){
				pre = p;
				flag = 1;
				p = p->rchild;
			} else if (p->data > data){
				pre = p;
				flag = 2;
				p = p->lchild;
			} else {
				//存在相同元素
				continue;
			}
		}
		p = mallocNewNode(data);

		if (flag == 1){
			pre ->rchild = p;
		} else {
			pre ->lchild = p;
		}
		
	}
	return root;
}
//遞歸插入二叉排序樹,非遞歸見上面的創建
void insertBST(BiNode ** p,int data){

	if ((*p) == NULL){
		(*p) = mallocNewNode(data);
		return;
	} else if ((*p)->data < data){
		insertBST(&((*p)->rchild),data);
	} else if ((*p)->data > data){
		insertBST(&((*p)->lchild),data);
	} else {
		return;
	}

}

void searchBST(BiNode* root, int data){
	BiNode* p = root;
	while(p != NULL){
		if (p->data < data){
			p = p->rchild;
		} else if (p->data > data){
			p = p->lchild;
		} else {

			printInfo("找到指定元素!\n");

			break;
		}
	}
	if (p == NULL){
		printInfo("沒有找到指定元素!\n");
	}
}




//刪除二叉排序樹中的元素
void deleteBST(BiNode **root,int data){

	 //首先找到指定結點。。
	 BiNode *p = *root;
	 BiNode *pre = NULL;
	 BiNode *temp = NULL;
	 BiNode *temppre = NULL;
	 int flag = 0;

	 while(p != NULL){
		 if (p->data < data){
			 flag = 1;//右子樹
			 pre = p;
			 p = p->rchild;
		 } else if (p->data > data){
			 flag = 2;//左子樹
			 pre = p;
			 p = p->lchild;
		 } else {
			 break;
		 }
	 }
	 if (p == NULL){
		 printInfo("沒有指定結點,無法執行刪除操作\n");
		 return ;	
	 }
	  
	 if (p ->lchild == NULL && p->rchild == NULL){
		//本身是葉子節點,刪除本身即可。
		
		 if (flag == 1){
			 pre ->rchild = NULL;
		 } else {
			 pre ->lchild = NULL;
		 }
		 free(p);
		
	 } else if ((p->rchild != NULL && p->lchild == NULL) || (p->rchild == NULL && p->lchild != NULL)){
		 //左或右子樹不爲空,則其值爲左或者右子樹
		
		 temp = p->rchild != NULL? p->rchild : p->lchild;
		
		 if (flag == 1){
			 pre ->rchild = temp;
		 } else {
			 pre ->lchild = temp;
		 }
		free(p);
		 

	 } else {
		
		 //直接前驅或者直接後繼。右子樹的最左側或者左子樹的最右側

		 temp = p ->lchild;
		 pre = p;
		 while(temp != NULL){
			 pre = temp;
			 temp = temp->rchild;
		 }
		//temp 此時爲空。將P結點替換爲左子樹的最右側結點
		 p->data = pre ->data;
		

		 //刪除左子樹的最右側結點
		 temp = p ->lchild;
		 temppre = p;
		
		 while(temp != pre){
			 temppre = temp;
			 temp = temp->rchild;
		 }

		 if (temppre == p){
			 temppre ->lchild = pre->lchild;
			 free(pre);
		 } else {
			 temppre ->rchild = pre->lchild;
			 free(pre);
		 }
		 
		 
	 }
}

//前序非遞歸遍歷
void preOrderTraverse(BiNode* root){

	BiNode * stack[MAX_SIZE];
	int top = -1;
	BiNode * p = root;

	while(p != NULL || top > -1){
		if ( p != NULL){
			printData2(p->data);
			stack[++top] = p;

			p = p->lchild;
		} else {
			p = stack[top--];
			p = p->rchild;
		}

	}



}
//中序非遞歸遍歷
void inOrderTraverse(BiNode* root){

	BiNode * stack[MAX_SIZE];
	int top = -1;
	BiNode * p = root;

	while(p != NULL || top > -1){

		while ( p != NULL){
			stack[++top] = p;
			p = p->lchild;
		}

		p = stack[top--];
		printData2(p->data);
		p = p->rchild;
	}

}
//後序非遞歸遍歷
void postOrderTraverse(BiNode* root){
	BiNode * stack[MAX_SIZE];
	int top = -1;
	BiNode * p = root,* pre;

	stack[++top] = p;  
	p = p->lchild;  

	while(top > -1){

		while (p != NULL){
			stack[++top] = p;
			p = p->lchild;
		}
		pre = NULL;
		//爲什麼要循環,因爲有可能在棧中多個結點的右子樹已經訪問過了,
		//已經具備了輸出的條件
		while (top > -1){

			p = stack[top];
			//其右子樹訪問過後,再訪問根節點
			if (p->rchild == pre){
				printData2(p->data);
				top--;//出棧
				pre = p;
			} else {
				//因爲右子樹還沒訪問,所以不能出棧,要停止循環,向右走一步之後向左走
				p = p->rchild;
				break;
			}
		}
	}

}

/****************************************二叉排序樹的操作結束**********************************************/


/*****************************************哈希表的操作開始********************************************/

typedef int KeyType; //設關鍵字域爲整形,需要修改類型時,只需修改這裏就可以  
const int NULLKEY=0; //NULLKEY表示該位置無值  

int hashsize[]={11,19,29,37,47}; //hash表容量遞增表  
int hash_length=0;//hash表表長 

typedef struct  {   //數據元素類型 
	int key;  
	int ord;   
}Elemtype;  

typedef struct {
	Elemtype *elem; //數據元素數組,動態申請  
	int count;// 當前數據元素個數  
	int size; //決定hash表的容量爲第幾個,hashsize[size]爲當前hash容量  
}HashTable;

HashTable * initHashTable(){
	HashTable *table =(HashTable *) malloc(sizeof(HashTable));
	
	int i = 0;
	table->count = 0;
	hash_length = table->size = hashsize[0];
	table->elem = (Elemtype *)malloc(sizeof(Elemtype)*hash_length);

	for(i=0;i<hash_length;i++){
		table->elem[i].key=NULLKEY;  
	}
		
	return table;

}

void destroy_HashTable(HashTable *&table){  
	
	free(table->elem);
	table->elem=NULL;  

	table->count=0;  
	table->size=0;  
}  

int Hash(int k){   //hash函數的一種(取模法)  
	return k%hash_length;  
}  

int Collision(int p,int d){  //解決衝突  
	 p = (p+d)%hash_length; //採用開放地址法裏的線性探測  
	 return p;
}  

int Search_Hash(HashTable *&table,int k){  //查找 
	//在開放地址hash表中查找關鍵字等於k的元素  
	//若找到用p表示待查數據,查找不成功時,p指向的是可插入地址  
	
	int c = 0,p = -1;
	p=Hash(k); //求hash地址  
	while(table->elem[p].key!=NULLKEY && table->elem[p].key!=k) {  
		c++;  
		if(c<hash_length){
			p = Collision(p,c); 
		} else {
			break;
		}
	}  
	if (c>=hash_length){
		return -1;
	}
	return p;
}  
int Insert_Hash(HashTable *&table,Elemtype e)  {  //插入 
	//在查找不成功的情況下將k插入到hash表中  
	int p,c = 0;  
	//printf("the key is %d and the pos is %d\n",e.key,Search_Hash(table,e.key));
	if(Search_Hash(table,e.key) == -1){
		return -1; //表示該元素已在hash表中  
	}else {
		p=Hash(e.key); //求hash地址

		while(table->elem[p].key!=NULLKEY) {  
			 c++;
			if(c<hash_length){
				p = Collision(p,c); 
			} else {
				p = -1;
				break;
			}
		}  
		//printData(p);
		if (p != -1){
			//插入e  
			
			table->elem[p]=e;  
			(table->count)++; 
			return 1;  
		} else {
			return -1;
		}
		 
		
	}  
	
}  


void Traverse_HashTable(HashTable *& hashTable){

	int i = 0;
	for(i = 0;i<hash_length;i++){

		if ((hashTable->elem[i].key) != NULLKEY){
			printData2(hashTable->elem[i].key);
		}
	}


}

void hashTableOperation(){
	HashTable * table = initHashTable();

	int i = 0;
	Elemtype type;
	for (i = 0;i<10;i++){
		type.key = nums1[i];
		Insert_Hash(table,type);
	}

	Traverse_HashTable(table);

}
/*****************************************哈希表的操作結束********************************************/
//判斷一個二叉樹是不是平衡二叉樹
int judgeIsAVLOrNot(BiNode * root){

	if (root== NULL){
		return 1;
	} else if (root->lchild == NULL && root->rchild == NULL){
		return 1;
	}else if ((root->lchild != NULL && root->lchild->rchild != NULL && root->rchild == NULL) ||
		(root->lchild != NULL && root->lchild->lchild != NULL && root->rchild == NULL) ||
		(root->rchild != NULL && root->rchild->rchild != NULL && root->lchild == NULL)||
		(root->rchild != NULL && root->rchild->lchild != NULL && root->lchild == NULL)){
			return 0;
	} else {
		return judgeIsAVLOrNot(root->rchild)*judgeIsAVLOrNot(root->lchild);
	}
	
}

//逆序輸出二叉排序樹
void destOrderTraverse(BiNode * root){

	if (root == NULL){
		return ;
	} 
	destOrderTraverse(root->rchild);
	printData2(root->data);
	destOrderTraverse(root->lchild);
}
//簡單哈希表,哈希函數爲餘數法,衝突處理方法爲開放地址法;
void smipleHash(){

	typedef struct HashTable{
		int *num;
		int count;
		int len ;

	}HashTable;

	//初始化
	int i = 0;
	HashTable table ;
	table.count = 0;
	table.len = 13;
	table.num = (int*)malloc(sizeof(int)*13);
	for (i = 0;i<table.len;i++){
		table.num[i] = -1;
	}
	
	int step;

	for (i = 0;i<10;i++){
		step = 1;
		if (table.num[nums3[i]%table.len] == -1){

			table.num[nums3[i]%table.len] = nums3[i];

			table.count++;
		} else {
			
			while(table.num[(nums3[i]+step)%table.len] != -1){
				step++;
			}
			
			table.num[(nums3[i]+step)%table.len] = nums3[i];
			table.count++;
		}
	}


	for (i = 0;i<table.len;i++){
		printData2(table.num[i]);
	}
	


}


void main(){
	printInfo("遞歸折半查找:\n");
	printData(binSearch(0,9,10));
	printInfo("\n\n");
	binSearch2(10);
	printInfo("\n\n");
	BiNode* root =  createBST();
	printInfo("前序:\n");
	preOrderTraverse(root);
	printInfo("\n");
	printInfo("中序:\n");
	inOrderTraverse(root);
	printInfo("\n");
	printInfo("後序:\n");
	postOrderTraverse(root);
	printInfo("\n\n");
	printInfo("二叉排序樹的查找:");
	searchBST(root,1);
	printInfo("\n\n");
	printInfo("二叉排序樹的刪除:");
	deleteBST(&root,7);
	inOrderTraverse(root);
	printInfo("\n\n");
	printInfo("二叉排序樹的插入:");
	insertBST(&root,7);
	inOrderTraverse(root);
	printInfo("\n\n");
	printInfo("哈希表的建立和輸出:\n");
	hashTableOperation();
	printInfo("\n\n");
	printInfo("二叉排序樹倒敘輸出:\n");
	destOrderTraverse(root);
	printInfo("\n\n");
	smipleHash();
	printInfo("\n\n");
	printInfo("判斷一個二叉樹是不是平衡二叉樹:\n");
	
	BiNode* root2 =  createBST();
	if (judgeIsAVLOrNot(root2) == 1){
		printInfo("平衡");
	} else {
		printInfo("不平衡");
	}
	printInfo("\n\n");
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章