查找算法

一、顺序查找(Seauential Search)(静态查找)

 

int SeqSearch(int s[],int n,int key)
{
    int i;
    for(i=0;i


 

二、折半查找 (Binary Search) (静态查找)

又称为二分查找,这种查找方法要求查找表的数据时线性结构保存,并且还要求查找表中的数据时按关键字由小到大有序排列。折半查找是一种递归过程。

最坏情况下,折半查找比较的次数O(nlog2n),其查找效率比顺序查找要快很多。

int BinarySearch(int s[],int n,int key)
{
    int low,high,mid;
    low=0;
    high=n-1;
    while(low<=high)        //查找范围含含至少一个元素 
    {
        mid=(low+high)/2;   //计算中间位置序号 
        if(s[mid]==key)      //中间元素与关键字相等 
            return mid;      //返回序号 
        else if(s[mid]>key)  //中间元素大于关键字 
            high=mid-1;     //重定义查找范围 
        else                 //中间元素小于关键字 
            low=mid+1;       //重定义查找范围 
    }
    return -1;               //返回查找失败 
}


优点:查找速度快,最多查找次数为O(nlog2n)。

缺点:对查找表中的数据有顺序要求,如果需要将查找不成功的关键字添加到查找表中,则需要对已有的查找表中的数据进行大量的移动

 

 

三、二叉排序树 (Binary Sorting Tree) (动态查找)

1、插入节点

假设t为树的根节点指针,再向该二叉树中增加新的关键字key。

typedef struct bst
{
    int data;
    struct bst *left;
    struct bst * right;
}BSTree;
void InsertBST(BSTree *t,int key)//在二叉排序树中插入查找关键字key
{
    BSTree *p,*parent,*head;
    if(!(p=(BSTree *)malloc(sizeof(BSTree *)))) //申请内存空间 
    {
        printf("申请内存出错!\n");
        exit(0); 
    }
    p->data=key; //保存结点数据 
    p->left=p->right=NULL; //左右子树置空    
    head=t;
    while(head) //查找需要添加的父结点 
    {
        parent=head;
        if(keydata) //若关键字小于结点的数据 
            head=head->left; //在左子树上查找 
        else                 //若关键字大于结点的数据 
            head=head->right;  //在右子树上查找                             
    }
    //判断添加到左子树还是右子树 
    if(keydata) //小于父结点 
        parent->left=p; //添加到左子树
    else           //大于父结点 
        parent->right=p; //添加到右子树 
}


2、创建二叉树(将数组保存到二叉树中)

 

void CreateBST(BSTree *t,int data[],int n)//n个数据在数组d中,tree为二叉排序树根
{
    int i;
    t->data=data[0];
    t->left=t->right=NULL;
    for(i=1;i


3、中序遍历(检查二叉树是否建立成功)

void BST_LDR(BSTree *t)  //中序遍历 
{
     if(t)//树不为空,则执行如下操作 
     {
         BST_LDR(t->left); //中序遍历左子树
         printf("%d ",t->data); //输出结点数据 
         BST_LDR(t->right); //中序遍历右子树/
     }
     return; 
} 


4、查找节点

在二叉树中查找指定的关键字key的过程:

①从根节点开始查找。

②若节点为空,则查找失败。

③若key值大小与跟节点数据相等,表示查找成功,返回节点指针。

④若key值小于节点的数据,继续在当前节点的左子树查找。

⑤若key值大于节点的数据,继续在当前节点的右子树查找。

BSTree *SearchBST(BSTree *t,int key)
{
    if(!t || t->data==key) //结点为空,或关键字相等 
        return t;          //返回结点指针
    else if(key>t->data) //关键字大于结点数据
        return(SearchBST(t->right,key));
    else
        return(SearchBST(t->left,key));
}


5、删除节点

删除二叉排序树中的一个节点,相当于删除有序序列中的一个记录,删除节点后需要调整二叉树,使其仍然保持二叉排序树的特点。

①删除的节点是二叉排序树的叶节点,即t->left  t->right都为null。由于删除该节点不会破坏二叉排序树的结构,只需要修改t节点的父节点的指针,并释放t节点占用内存即可。

②若t节点只有一个子树(即t->left   t->right有一个为空),这时,只需要修改t节点的父节点,使其子节点指针的值为t->left  或者 t->right 即可。

③若t节点有两个子树,此时的操作相对复杂些,需要从二叉排序树的中序遍历中找到被删除节点的后继节点

void BST_Delete(BSTree *t,int key)
{
    BSTree *p,*parent,*l,*l1;
    int child=0;//0表示左子树,1表示右子树 
    if(!t) return;     //二叉排序树为空,则退出
    p=t;
    parent=p;
    while(p)           //二叉排序树有效 
    {        
        if(p->data==key)
        {
            if(!p->left && !p->right) //叶结点(左右子树都为空) 
            {
                if(p==t) //被删除的是根结点 
                {
                    free(p);//释放被删除结点 
                }
                else if(child==0) //父结点为左子树 
                {
                    parent->left=NULL; //设置父结点左子树为空 
                    free(p); //释放结点空间 
                }
                else //父结点为右子树 
                {
                    parent->right=NULL; //设置父结点右子树为空 
                    free(p); //释放结点空间 
                }
            }
            else if(!p->left) //左子树为空,右子树不为空
            {
                if(child==0) //是父结点的左子树
                    parent->left=p->right;
                else //是父结点的右子树             
                    parent->left=p->left;
                free(p); //释放被删除结点
            }
            else if(!p->right)//右子树为空,左子树不为空
            {
                 if(child==0) //是父结点的左子树
                    parent->right=p->right;
                else //是父结点的右子树             
                    parent->right=p->left;
                free(p); //释放被删除结点       
            }
            else  //左右子树都不为空 
            {
                l1=p; //保存左子树的父结点 
                l=p->right; //从当前结点的右子树进行查找 
                while(l->left) //左子树不为空 
                {
                    l1=l;
                    l=l->left; //查找左子树 
                }
                p->data=l->data; //将左子树的数据保存到被删除结点
                l1->left=NULL; //设置父结点的左子树指针为空 
                free(l1); //释放左子树占的内存空间
            }
            p=NULL;
        }
        else if(keydata) //需删除记录的关键字小于结点的数据 
        {
            child=0;//标记在当前结点左子树查找
            parent=p; //保存当前结点作父结点 
            p=p->left; //查找右子树 
        }
        else //需删除记录的关键字大于结点的数据 
        {
            child=1;//标记在当前结点右子树查找
            parent=p;//保存当前结点作父结点 
            p=p->right; //查找右子树 
        }    
    } 
}


 

 

6、main主函数测试代码是否正确

int main()
{
    int i,key;
    BSTree bst,*pos; //保存二叉排序树根结点
    printf("原数据:"); 
    for(i=0;i


 

 

 

 

你可能感兴趣的:(数据结构)