Chapter 8(查找)


1.二分查找和插值查找
//************************Search.h***********************************
#ifndef SEARCH_H
#define SEARCH_H

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

int BiSearch(int array[],int n,int key);

int IVSearch(int array[],int n,int key);

int FibSearch(int array[],int n,int key);



#endif //SEARCH_H


//************************Search.c*************************************
#include "Search.h"


//折半查找
int BiSearch(int array[],int n,int key)
{
	if(NULL == array)return -1;
	int left = 0;
	int right= n-1;
	int mid  = (left+right)/2;

	while(left <= right)
	{
		if(array[mid] == key)
		{
			return mid;
		}
		else if(array[mid] > key)
		{
			right = mid-1;
		}
		else if(array[mid] < key)
		{
			left = mid+1;
		}
		mid = (left+right)/2;
	}
	return -1;
}


//插值查找
int IVSearch(int array[],int n,int key)
{
	if(NULL == array)return -1;
	int left = 0;
	int right= n-1;
	int mid  = left+(right-left)*(key-array[left])/(array[right]-array[left]);

	while(left <= right)
	{
		if(array[mid] == key)
		{
			return mid;
		}
		else if(array[mid] > key)
		{
			right = mid-1;
		}
		else if(array[mid] < key)
		{
			left = mid+1;
		}
		mid  = left+(right-left)*(key-array[left])/(array[right]-array[left]);
	}
	return -1;
}



int FibSearch(int array[],int n,int key)
{
	int F[] = {1,1,2,3,5,8,13,21,34,55,89};
	

	int left = 0;
	int right= n-1;
	int mid;

	int k = 0;
	while(n>F[k]-1)
	{
		k++;
	}
	for(int i=n;i < F[k])

}


//************************SearchTest.c*************************************
#include "Search.h"


int main()
{
	int a[10] = {1,16,24,35,47,59,62,73,88,99};
	int key = 62;

	printf("position: %d \n",BiSearch(a,10,key));
	printf("position: %d \n",IVSearch(a,10,key));
}


2.斐波那契查找
#include <stdio.h>  
#include <stdlib.h>  
#define MAXN 20  
  
/* 
 *产生斐波那契数列 
 * */  
void Fibonacci(int *f)  
{  
    int i;  
    f[0] = 1;  
    f[1] = 1;  
    for(i = 2;i < MAXN; ++i)  
        f[i] = f[i - 2] + f[i - 1];  
}  
  
/* 
 * 查找 
 * */  
int Fibonacci_Search(int *a, int key, int n)  
{  
    int i, low = 0, high = n - 1;  
    int mid = 0;  
    int k = 0;  
    int F[MAXN];  
    Fibonacci(F);  
    while(n > F[k] - 1)          //计算出n在斐波那契中的数列  
        ++k;  
    for(i = n;i < F[k] - 1;++i) //把数组补全  
        a[i] = a[high];  
    while(low <= high)  
    {  
        mid = low + F[k-1] - 1;  //根据斐波那契数列进行黄金分割  
        if(a[mid] > key)  
        {  
            high = mid - 1;  
            k = k - 1;  
        }  
        else if(a[mid] < key)  
        {  
            low = mid + 1;  
            k = k - 2;  
        }  
        else  
        {  
            if(mid <= high) //如果为真则找到相应的位置  
                return mid;  
            else  
                return -1;  
        }  
    }  
    return 0;  
}  
  
int main()  
{     
    int a[MAXN] = {5,15,19,20,25,31,38,41,45,49,52,55,57};  
    int k, res = 0;  
    printf("请输入要查找的数字:\n");  
    scanf("%d", &k);  
    res = Fibonacci_Search(a,k,13);  
    if(res != -1)  
        printf("在数组的第%d个位置找到元素:%d\n", res + 1, k);  
    else  
        printf("未在数组中找到元素:%d\n",k);  
    return 0;  
}  


3.二叉排序树
//****************************BiSortTree.h*************************
#ifndef BISORTTREE_H
#define BISORTTREE_H


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

typedef int datatype;

typedef struct BiSNode
{
	datatype data;
	struct BiSNode *left,*right;
}BiSNode,*BiSTree;


//在二叉排序树中查找key
bool SearchBST(BiSTree T,datatype key,BiSTree f,BiSTree *p);

//按顺插入
bool InsertBST(BiSTree *T,datatype key);

//删除节点
bool DeleteBST(BiSTree *T,datatype key);


bool Delete(BiSTree *p);


#endif  //BISORTTREE_H


//****************************BiSortTree.c*************************
#include "BiSortTree.h"

//在二叉排序树中查找key
bool SearchBST(BiSTree T,datatype key,BiSTree f,BiSTree *p)
{
	if(!T)
	{
		*p = f;
		return false;
	}
	else if(key == T->data)
	{
		*p = T;
		return true;
	}
	else if(key < T->data)
	{
		return SearchBST(T->left,key,T,p);
	}
	else
	{
		return SearchBST(T->right,key,T,p);
	}
}

//按顺插入
bool InsertBST(BiSTree *T,datatype key)
{
	BiSTree p,s;
	if(!SearchBST(*T,key,NULL,&p))
	{
		s = (BiSTree)malloc(sizeof(BiSNode));
		s->data = key;
		s->left = s->right = NULL;

		if(!p)
		{
			*T = s;
		}
		else if(key < p->data)
		{
			p->left = s;
		}
		else 
		{
			p->right = s;
		}
		return true;
	}
	else
	{
		return false;
	}
}

//删除节点
bool DeleteBST(BiSTree *T,datatype key)
{
	if(!*T)
	{
		return false;
	}
	else
	{
		if(key == (*T)->data)
		{
			return Delete(T);
		}
		else if(key < (*T)->data)
		{
			DeleteBST(&(*T)->left,key);
		}
		else
		{
			DeleteBST(&(*T)->right,key);
		}
	}
}

bool Delete(BiSTree *p)
{
	BiSTree q,s;

	if(NULL == (*p)->left)
	{
		q = *p;
		*p = (*p)->right;
		free(q);
	}
	else if(NULL == (*p)->right)
	{
		q = *p;
		*p = (*p)->left;
		free(q);
	}
	else
	{
		q = *p;
		s = (*p)->left;

		while(s->right)
		{
			q = s;
			s = s->right;
		}
		(*p)->data = s->data;

		if(q != *p)
		{
			q->right = s->left;
		}
		else
		{
			q->left  = s->left;
		}
		free(s);
	}
	return true;
}

//****************************BiSortTreeTest.c*************************
#include "BiSortTree.h"



int main()
{
	int i;
	int a[10] ={62,88,58,47,35,73,51,99,37,93};
	BiSTree T = NULL;
	for(i = 0;i < 10;i++)
	{
		InsertBST(&T,a[i]);
	}
	
	BiSTree p,f;
	printf("%d \n",p->data);
	SearchBST(T,58,f,&p);
	printf("%d \n",p->data);

	DeleteBST(&T,58);

	printf("%d \n",p->data);
}

4.AVL(平衡二叉树)
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#define EH 0            /*等高*/
#define LH 1            /*左高*/
#define RH -1            /*右高*/
    
typedef int ElemType;                 /*数据类型*/

typedef struct BiTree{
    ElemType data;                    /*数据元素*/
    int BF;                         /*平衡因子*/
    struct BiTree *lchild,*rchild;     /*左右子女指针*/
}*Bitree,BitreeNode;


int InsertAVL(Bitree *T,ElemType e,bool *taller);
void LeftBalance(Bitree *T);
void RightBalance(Bitree *T);
void R_Rotate(Bitree *T);
void L_Rotate(Bitree *T);
bool *taller;
//bool *taller= (bool *)malloc(sizeof(bool));

int main(void)
{
    taller= (bool *)malloc(sizeof(bool));
    int data;
    Bitree T=NULL;
    while(1)
    {
        printf("enter the number(zero to exit):");
        scanf("%d",&data);
        if(0==data)break;
        InsertAVL(&T,data,taller);
        
    }
    
    
    
    return 0;
}


/*若在平衡的二叉排序树T 中不存在和e 有相同关键码的结点,则插入一个数据元素为e 的*/
/*新结点,并反回1,否则反回0。若因插入而使二叉排序树失去平衡,则作平衡旋转处理,*/        
/*布尔型变量taller 反映T 长高与否*/    
int InsertAVL(Bitree *T,ElemType e,bool *taller)
{
    if(!*T)                /*插入新结点,树“长高”,置taller 为TURE*/
    {
        (*T)=(Bitree)malloc(sizeof(BitreeNode));
        (*T)->data = e;
        (*T)->lchild = (*T)->rchild = NULL;
        (*T)->BF = EH;
        *taller = true;
    }
    else
    {
        if(e==(*T)->data)        /*树中存在和e 有相同关键码的结点,不插入*/
        {
            *taller = false;
            return 0;
        }    
        if(e<(*T)->data)
        {
            if(!InsertAVL(&(*T)->lchild,e,taller))    return 0;  /*未插入*/
            if(*taller)
            switch((*T)->BF)
            {    
                case EH :                    /*原本左、右子树等高,因左子树增高使树增高*/
                    (*T)->BF=LH;
                    *taller=true;
                    break;
                
                case LH :                    /*原本左子树高,需作左平衡处理*/
                    LeftBalance(T);
                    *taller=false;
                    break;
                
                case RH :                    /*原本右子树高,使左、右子树等高*/
                    (*T)->BF=EH; 
                    *taller=false;
                    break;
                    
            }
            
        }
        else
        {
            if(!InsertAVL(&(*T)->rchild,e,taller))    return 0;  /*未插入*/
            if(*taller)
            switch((*T)->BF)
            {    
                case EH :                    /*原本左、右子树等高,因右子树增高使树增高*/
                    (*T)->BF=RH;
                    *taller=true;
                    break;
                
                case LH :                    /*原本左子树高,使左、右子树等高*/
                    (*T)->BF=EH; 
                     *taller=false;
                     break;
                
                case RH :                    /*原本右子树高,需作右平衡处理*/
                    RightBalance(T);
                    *taller=false;
                     break;
                    
            }
        }
    }
    return 1;
}



/*对以*p 指向的结点为根的子树,作左平衡旋转处理,处理之后,*p 指向的结点为子树的新根*/
void LeftBalance(Bitree *T)
{
    Bitree L=(*T)->lchild,Lr;             /*L 指向*T左子树根结点*/
    switch(L->BF)                /*检查L 平衡度,并作相应处理*/
    {
        case LH:                    /*新结点插在*p 左子树的左子树上,需作单右旋转处理*/
            (*T)->BF=L->BF=EH;
             R_Rotate(T);
             break;
        case EH:             /*原本左、右子树等高,因左子树增高使树增高*/
            (*T)->BF=LH;    //这里的EH好像没有写的必要 
              *taller=true;
              break;
        case RH:                     /*新结点插在*T 左孩子的右子树上,需作先左后右双旋处理*/
            Lr=L->rchild;             /*Lr 指向*p 左孩子的右子树根结点*/    
            switch(Lr->BF)         /*修正*T 及其左子树的平衡因子*/
            {
                case LH:
                    (*T)->BF = RH;
                    L->BF = EH;
                    break;
                case EH:
                    (*T)->BF = L->BF= EH;
                    break;
                case RH:
                    (*T)->BF = EH;
                    L->BF = LH;
                    break;
                
            }
            Lr->BF = EH;
            L_Rotate(&L);        /*对*T 的左子树作左旋转处理*/
            R_Rotate(T);        /*对*T 作右旋转处理*/
    }
}
//这里和leftbalance一个道理,试着自己写一下 
void RightBalance(Bitree *T)
{
    Bitree Lr= (*T)->rchild,L;
    switch(Lr->BF)
    {
        case EH:
            *taller = true;
            (*T)->BF = RH;
            break;
        case RH:
            (*T)->BF=Lr->BF=EH;
            L_Rotate(T);
            break;
        case LH:
            L = Lr->lchild;
            switch(L->BF)
            {
                case EH:
                    (*T)->BF=Lr->BF= EH;
                    break;
                case RH:
                    Lr->BF= EH;
                    (*T)->BF = LH;
                    break;
                case LH:
                    (*T)->BF = LH;
                    Lr->BF = EH;
                    break;
                
            }
            L->BF = EH;
            R_Rotate(&Lr);        
            L_Rotate(T);    
        
    }
}


/*对以*T 指向的结点为根的子树,作右单旋转处理,处理之后,*T 指向的结点为子树的新根*/
void R_Rotate(Bitree *T)
{ 
    Bitree L=(*T)->lchild;                 /*L 指向*T 左子树根结点*/
    (*T)->lchild=L->rchild;                 /*L 的右子树挂接*T 的左子树*/
    L->rchild=*T; *T=L;             /* *L 指向新的根结点*/
}


/*对以*p 指向的结点为根的子树,作左单旋转处理,处理之后,*p 指向的结点为子树的新根*/
void L_Rotate(Bitree *T)
{ 
    Bitree Lr=(*T)->rchild;                 /*Lr 指向*T 右子树根结点*/
    (*T)->rchild=Lr->lchild;                 /*L 的左子树挂接*p 的右子树*/
    Lr->lchild=*T; 
    *T=Lr;                                     /* *L 指向新的根结点*/
}

附件列表

 

posted @ 2018-07-17 22:25  LyndonMario  阅读(252)  评论(0编辑  收藏  举报