搜索查找 - 算法学习

来源:互联网 发布:java和php全面对比 编辑:程序博客网 时间:2024/05/19 00:10

       搜索是一种以集合为逻辑结构,以查找为核心的运算,同时包括其他运算的数据结构。

1.1 静态搜索 - 该方法是基于顺序表作为存储结构的,然后在这个结构上执行运算。

       1.1 顺序搜索

        岗哨a[0]保证while循环一定会终止,这样的话不用将i > 0写入循环条件,是循环条件简化

//len为数组的长度,x是要查找的元素值int Search(int a[], int len, int x){    int i = len;    a[0] = x;    while(a[i] != x)        i--;    return i;}

1.2 折半搜索法

        在一个有序表中可以用效率更高的折半搜索法进行查找,在每一次如果未找到搜索元素,则进一步缩小搜索的范围。折半搜索的思想是:每次将搜索区间的中间元素和给定

的值K比较,若不相等就缩小范围并在新的范围内重复上述过程,直至搜索成功返回0(或者搜索不成功为止)。当然这些都是在数组元素都进行排序之后再进行的。

int Compare(int a, int b){    if(a > b)        return 1;    else if(a < b)        return -1;    else        return 0;}int BinSearch(int a[], int len, int x){    int mid, low = 0;    int high = len;    while(low <= high)    {        mid = (low + high) / 2;        switch(Compare(a[mid], x))        {        case 0:  return (mid);        case -1: low += 1; break;        case 1:  high = mid -1; break;        }    }    return 0;}


2 二叉搜索树

        二叉搜索树定义:是空树或者满足已下性质的二叉树:

        (1) 若它的左子树非空,则左子树的所有节点都小于根节点

        (2) 若它的右子树非空,则右子树的所有节点都小于根节点

        (3) 左右子树本身又各是二叉搜索树

        (4) 每个元素都有一个关键值,且没有任何两个元素有相同的关键值,所有关键值都是唯一的。

2.1二叉搜索树的搜索:

        递归算法为在指针root所指的二叉搜索树的键值是否等于key的节点,成功返回该节点的指针,否则返回空指针。改程序中以输入0为终止符

#include <stdio.h>#include <stdlib.h>typedef int datatype;typedef struct node{    datatype data;    struct node *lchild, *rchild;}Tree, *pTree;pTree CreatTree(void);void ShowTree(pTree root);void FreeTree(pTree root);pTree CreatTree(void){    pTree p;    int x;    scanf("%d", &x);    if(x == 0)        p = NULL;    else    {        p = (Tree *)malloc(sizeof(Tree));        p->data = x;        p->lchild = CreatTree();        p->rchild = CreatTree();    }    return p;}void ShowTree(pTree root){    if(root)    {        printf("%d ", root->data);        ShowTree(root->lchild);        ShowTree(root->rchild);    }}void FreeTree(pTree root){    if(root)    {        FreeTree(root->lchild);        FreeTree(root->rchild);        free(root);    }}int Compare(int a, int b){    if(a > b)        return 1;    else if(a < b)        return -1;    else        return 0;}pTree TreeSearch(pTree root, datatype key){    if(root == NULL)        return NULL;    else    {        switch(Compare(root->data, key))        {        case 0:  return (root);        case -1: return (TreeSearch(root->rchild, key));        case 1:  return (TreeSearch(root->lchild, key));        }    }}int main(void){    pTree root, p;    root = CreatTree();    ShowTree(root);    putchar('\n');    if((p = TreeSearch(root, 5)) != NULL)        printf("\nthe location is %d.\n", p->data);    FreeTree(root);    printf("\nFree the tree is ok.\n");    return 0;}
2.2 二叉搜索树的插入

        二叉搜索树的插入必须保证插入一个节点后仍是一个二叉搜索树,另外,当二叉搜索树中不存在也键值相等的元素时才能插入这样一个节点。因此插入算法必须包含搜索过

程,并且当搜索不成功时实施新节点插入操作。

二叉搜索树的插入:

pTree TreeInsert(pTree root, datatype key){    pTree p;    if(root == NULL)    {        p = (Tree *)malloc(sizeof(Tree));        p->data = key;        p->lchild = NULL;        p->rchild = NULL;        return (p);    }    else    {        switch(Compare(root->data, key))        {        case 0:  return (root);        case -1: root->rchild = TreeInsert(root->rchild, key); return root;        case 1:  root->lchild = TreeInsert(root->lchild, key); return root; //在左右子树插入后返回原根指针        }    }    return NULL;}

2.3 二叉树的删除

        删除后仍需保持为一颗二叉搜索树,设被删节点为P,其双亲节点为F,P是F的左孩子,则有一下3中情况:

        (1) P为叶节点,只需将F的左指针为空

        (2) P只有一棵非空子树,则删除P并直接令P的该非空子树为F的左子树,即以P的非空子树取代P的位置

        (3) P有两个非空子树,只需将该元素替换为它的左子树中的最大值或者则是右子树的最小值

二叉搜索树的删除

//返回值0为成功返回,-1为未找到int DeleteTree(pTree root, datatype key){    Tree *parent=NULL, *p = root;    Tree *q, *child;    while(p)    {        if(p->data == key)            break;        parent = p;        p = (key < p->data) ? p->lchild : p->rchild;    }    if(!p)        return -1;  //找不到被删节点返回    q = p;    if(q->lchild && q->rchild)  //q的两个孩子均非空,则找q的中序后继p        for(parent = q, p = q->rchild; p->lchild; parent = p, p = p->lchild)            ;    child = (p->lchild) ? p->lchild : p->rchild;    if(!parent)        root = child;    else    {           //p不是根,则将p的孩子和p的双亲进行链接,p被删除        if(p == parent->lchild)            parent->lchild = child;        else            parent->rchild = child;        if(p != q)            q->data = p->data;    }    free(p);    return 0;}


3 AVL树

空的二叉树是AVL树,如果T是一棵非空的二叉树,TL和TR分别是左子树和右子树,则T满足以下条件时,T是一棵AVL树

        (1) TL和TR是AVL树

        (2) |hL-hR|<=1,TL和TR分别是左子树和右子树的高度

        AVL搜索树既是二叉搜索树,也是AVL数

基本操作实现:

3.1 AVL数的搜索

        因为n个元素的AVL树的高度是O(log2(n)),所以搜索所需时间是O(nlog2(n))

3.2 AVL搜索树的插入

        AVL数的插入算法应在二叉搜索树的插入算法基础上扩充以下功能:

        (1) 判断插入节点之后是否失平衡

        (2) 若是,寻找最小失衡子树并跳转

        (3) 判断失衡类型并做相应调整

#include "stdio.h"typedef  struct info {int  key;}element;struct tree_node {struct tree_node *  left_child;    element   data;    short  int  bf;    struct tree_node*  right_child;};typedef struct tree_node tree;typedef  struct tree_node  *AVL_pt;int IS_FULL(AVL_pt ptr){return (!ptr);}void left_rotation( AVL_pt parent , int *unbalanced ){        AVL_pt grand_child , child ;         child = parent->left_child ;         if ( child->bf == 1 ){           /* LL 转置 */           parent->left_child = child->right_child ;            child->right_child = parent ;            parent->bf = 0 ;            parent = child ;         }        else {        /* LR 转置 */           grand_child = child->right_child ;            child->right_child = grand_child->left_child ;            grand_child->left_child = child ;            parent->left_child = grand_child->right_child ;            grand_child->right_child = parent ;            switch( grand_child->bf ){                  case 1:  parent->bf = -1 ;                            child->bf = 0 ;                            break ;                   case 0:  parent->bf = child->bf = 0 ;                            break ;                   case -1: parent->bf = 0 ;                            child->bf = 1 ;            }           parent = grand_child ;         }        parent->bf=0;         *unbalanced=0 ; }       void insert( AVL_pt parent , element x ,  int *unbalanced ){  if ( !parent ){   /* 插入新元素 */       *unbalanced = 1 ;        parent= (AVL_pt) malloc(sizeof(tree)) ;        if (IS_FULL(parent) ){           printf("The memory is  full\n" ) ;            exit(1) ;        }       parent->left_child = ( parent )->right_child = NULL ;        parent->bf = 0 ;        parent->data = x ;    }   else if ( x.key < ( parent )->data.key ){       insert(parent->left_child , x , unbalanced ) ;        if ( *unbalanced )       /* 左支树高 */          switch( ( parent )->bf ){             case -1: ( parent )->bf = 0 ;                        *unbalanced = 0 ;     break ;              case 0:  ( parent )->bf = 1 ;        break ;              case 1:  left_rotation( parent , unbalanced ) ;           }   }   else if ( x.key > ( parent )->data.key ){      insert(parent->right_child , x , unbalanced ) ;        if ( *unbalanced )           /*右支树高*/           switch ( parent->bf ){              case 1:  parent->bf = 0 ;                        *unbalanced = 0 ;      break ;               case 0:  parent->bf = -1 ;       break ;               case -1:// right_rotation( parent , unbalanced )   ;            }   }   else {  *unbalanced = 0 ;        printf( "The key is already in the tree" ) ;    }}void main(){int  unbalanced=0;element x;AVL_pt  root;x.key=10;root=NULL;insert (root, x, &unbalanced );}


0 0
原创粉丝点击