• 数据结构总复习(查找)


    线性表查找分为顺序查找和折半查找

    1)顺序查找:从表中最后一个记录开始,逐个进行记录的关键字和给定值比较,相等,则返回元素在表中的位置。

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 typedef struct{
     4 int *elem;
     5 int length;
     6 }SSTable;
     7 int Search_Seq(SSTable st,int key)
     8 {
     9    st.elem[0]=key;
    10    for(int i=st.length;(st.elem[i]!=key)&&(i>0);--i) ;
    11         return i;
    12   if(i==0)
    13   {
    14       printf("抱歉,没有找到相应的元素!");
    15   }
    16 }
    17 int main()
    18 {
    19     int *b;
    20     int n,k,s=0;
    21     SSTable st;
    22     printf("请输入元素的总个数:
    ");
    23     scanf("%d",&n);
    24     st.elem=(int *)malloc((n+1)*sizeof(int));
    25     st.length=n;
    26     b=st.elem;
    27     b++;
    28     printf("输入各元素的值:
    ");
    29     for(int i=0;i<n;i++,b++)
    30         scanf("%d",b);
    31     printf("请输入要查找的值:
    ");
    32     scanf("%d",&k);
    33     s=Search_Seq(st,k);
    34     if(s!=0)
    35     printf("%d",s);
    36 }
    View Code

    有意思(以前写的代码,刚刚注意到scanf("%d",b)因为是多次输入需要在前面加空格,可是这次不加也可以了。)对scanf函数还没有很好的理解。。

    我又犯傻了:(之前的代码有写注释的,我刚刚改了代码,但是不需要改的。。。)

    补充:在查找之前先对st.elem[0]的关键字赋值key,目的在于免去查找过程中每一步都要检测整个表是否查找完毕。这也是这个算法的妙处

    2)折半查找:以处于区间中间位置记录的关键字和给定值进行比较,若相等,则查找成功,不等则缩小范围,直至新的区间中间位置记录的值和给定的值相等。(针对有序表

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 typedef struct{
     4 int *elem;
     5 int length;
     6 }SSTable;
     7 int Search_Seq(SSTable st,int key)
     8 {
     9     int low=1,high=st.length,mid;
    10     while(low<=high)
    11     {
    12         mid=(low+high)/2;
    13         if(st.elem[mid]==key)
    14             return mid;
    15         else if(key<st.elem[mid])
    16             high=mid-1;
    17         else
    18             low=mid+1;
    19     }
    20     return 0;
    21 }
    22 int main()
    23 {
    24     int *b;
    25     int n,k,s=0;
    26     SSTable st;
    27     printf("请输入元素的总个数:
    ");
    28     scanf("%d",&n);
    29     st.elem=(int *)malloc((n+1)*sizeof(int));
    30     st.length=n;
    31     b=st.elem;
    32     b++;
    33     printf("输入各元素的值:
    ");
    34     for(int i=0;i<n;i++,b++)
    35         scanf("%d",b);
    36     printf("请输入要查找的值:
    ");
    37     scanf("%d",&k);
    38     s=Search_Seq(st,k);
    39     if(s!=0)
    40     printf("%d",s);
    41 }
    View Code

     3)二叉排序树

     概念:

    1)  若根节点有左子树,则左子树的所有节点都比根节点要小

    2)  若根节点有右子树,则右子树的所有节点都比根节点要大

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 
      6 namespace BinarySortTree
      7 {
      8     public class Program
      9     {
     10         //定义一个二叉排序树结构
     11         public class BSTree
     12         {
     13             public int data;
     14             public BSTree left;
     15             public BSTree right;
     16         }
     17         #region 创建二叉序树
     18         static BSTree CreateBST(List<int> list)
     19         {
     20             BSTree bstree = new BSTree()
     21             {
     22                data=list[0],
     23                left=null,
     24                right=null
     25             };//构造函数
     26             for (int i = 1; i < list.Count; i++)
     27             {
     28                 bool isExcute = false;
     29                 InsertBST(bstree,list[i],ref isExcute);
     30             }
     31             return bstree;    
     32         }
     33         #endregion
     34         #region 插入值到二叉树中
     35         static void InsertBST(BSTree bstree, int key,ref bool isExcute)
     36         {
     37             if (bstree == null)
     38                 return;
     39             if (bstree.data > key)//体会这里设计的妙处,如果大于的话就会递归调用这个函数,最后得到底层的,根书上的算法实现的功能类似,只不过,书上是用查找实现了,这一步可能还好些,因为避免出入相同的值
     40                 InsertBST(bstree.left, key, ref isExcute);
     41             else
     42                 InsertBST(bstree.right,key,ref isExcute);
     43             
     44             if (!isExcute)
     45             {
     46                 BSTree current = new BSTree()
     47                 {
     48                     data=key,
     49                     left=null,
     50                     right=null
     51                 };
     52                 //插入到父节点的当前元素
     53                 if (bstree.data > key)
     54                     bstree.left = current;
     55                 else
     56                     bstree.right = current;
     57                 isExcute = true;
     58             }
     59         }
     60         #endregion
     61         #region 查找节点
     62         static bool SearchBST(BSTree bstree, int key)
     63         {
     64             if (bstree == null)
     65                 return false;
     66             if (bstree.data == key)
     67                 return true;
     68             if (bstree.data > key)
     69                 return SearchBST(bstree.left, key);
     70             else
     71                 return SearchBST(bstree.right,key);
     72         }
     73         #endregion
     74         static void LDR_BST(BSTree bstree)
     75         {
     76             if (bstree != null)
     77             {
     78                 LDR_BST(bstree.left);
     79                 Console.Write(bstree.data + "");
     80                 LDR_BST(bstree.right);
     81             }
     82         }
     83         static void DeleteBST(ref BSTree bstree,int key)
     84         {
     85             if (bstree == null)
     86                 return;
     87             if (bstree.data == key)
     88             {
     89                 //为叶子节点
     90                 if (bstree.left == null && bstree.right == null)
     91                 {
     92                     bstree = null;
     93                     return;
     94                 }
     95                 //左子树不为空
     96                 if (bstree.left != null && bstree.right == null)
     97                 {
     98                     bstree = bstree.left;
     99                     return;
    100                 }
    101                 //右子树不为空
    102                 if (bstree.right != null && bstree.left == null)
    103                 {
    104                     bstree = bstree.right;
    105                     return;
    106                 }
    107                 //左右子树都不为空
    108                 if (bstree.left != null && bstree.right != null)
    109                 {
    110                     var node = bstree.right;//被删除节点的右孩子
    111                     BSTree lastNode = bstree;
    112                     while (node.left != null)
    113                     {
    114                         lastNode = node;
    115                         node = node.left;
    116                     }
    117                     bstree.data = node.data;//实现交换
    118                     if (lastNode.right == node)
    119                     {//删除节点的右节点没有左节点,有点拗口,不过理解了就好!
    120                         bstree.right = node.right;
    121                     }
    122                     else
    123                     {
    124                         if (lastNode.left == node)
    125                         {
    126                             lastNode.left = node.right;
    127                         }
    128                     }
    129                     node = null;
    130                 }
    131             }
    132             if (bstree.data > key)
    133             {
    134                 DeleteBST(ref bstree.left, key);
    135             }
    136             else
    137             {
    138                 DeleteBST(ref bstree.right,key);
    139             }
    140         }
    141         static void Main(string[] args)
    142         {
    143             List<int> list = new List<int>() {50,30,70,10,40,90,80};
    144             BSTree bstree = CreateBST(list);
    145             Console.Write("中序遍历的原始数据:");
    146             LDR_BST(bstree);
    147             Console.Write("------------
    ");
    148             //查找一个节点
    149             Console.WriteLine("在二叉树中是否包含:"+SearchBST(bstree,10));
    150             Console.Write("------------
    ");
    151             bool isExcute = false;
    152             InsertBST(bstree,20,ref isExcute);
    153             Console.WriteLine("插入到二叉树,中序遍历后:");
    154             LDR_BST(bstree);
    155             Console.Write("------------
    ");
    156             Console.Write("删除叶子节点20,中序遍历后结果为:");
    157             DeleteBST(ref bstree,20);
    158             LDR_BST(bstree);
    159             Console.Write("删除叶子节点90,中序遍历后结果为:");
    160             DeleteBST(ref bstree, 90);
    161             LDR_BST(bstree);
    162             Console.ReadLine();
    163         }
    164     }
    165 }
    View Code


    4)哈希查找:

    首先理解下哈希函数,比如5是一个要保存的数,丢给哈希函数后,返回一个2.那么此时5和2就建立了一种关系,这种关系就是哈希关系,在应用中,2是key,5是value

    如何构造哈希函数:

    1),直接定址法:

       Key=value+c; c为一个常量,value+c就是一个简单的哈希函数

    2),除法取余

      Key=value%c;

    3),数学分析法:

      比如一组value1=112233,value2=112633,value3=119033,针对这样的数我们分析中间两个数比较波动,其他数不变,那么取key的值就可以是key1=22,key2=26,,key3=90

    4),平方取中法:

      取关键字平方后的中间几位为哈希地址。

    5),折叠法

       移位叠加:将分割后的每一部分的最低位对齐,然后相加;

       间接叠加:从一端向另一端沿分割界来回折叠,然后对齐相加

    如:0-442-20586-4

    移位相加为 5864+4220+04=10088,去掉1为0088;

    间接叠加为:5864+0224+04=6092

    6),随机数法:

     选择一个随机函数,取关键字的随机函数值作为它的哈希地址。

    解决冲突的手法有:

    1,  开放地址法:

    Hi=(H(key)+di)MODm  i=1,2,....k

    1),di=1,2,3,4..m,称为线性探测再散列

    2),di=1^2,-1^2,2^2,称为二次探测再散列

    3),di为伪随机数序列,称为为随机探测再散列

     2,再哈希法

    Hi=RHi(key)

    Rhi是不同的哈希函数

    3,  链地址法

    将所有关键字哈希的值相同的记录存储在同一线性链表中。

    4,  建立一个公共溢出区

    发生冲突后就填入溢出表。

    用除法取余的方法构造哈希函数,用开放地址法中的线性探测再散列解决冲突。代码如下

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 
     6 namespace Hash
     7 {
     8     class Program
     9     {
    10         static int hashlength=13;
    11         static int[] hash=new int[hashlength];//定义哈希表长度
    12         //原数据
    13         static List<int> list=new List<int>{10,20,64,32,55,42};
    14         
    15         static int  SearchHash(int key,int hashlength,int[] hash)
    16         {
    17             int hashAddress = key % hashlength;
    18             //指定hashAddress对应值存在但不是关键值,则用开放寻址法解决
    19             while(hash[hashAddress]!=0&&hash[hashAddress]!=key)
    20             {
    21                 hashAddress = (++hashAddress) % hashlength;
    22             }
    23             //查找到开放单元,也就是没有数据的单元
    24             if (hash[hashAddress] == 0)
    25                 return -1;
    26             return hashAddress;
    27         }
    28         static void InsertHash(int[] hash, int hashlength, int data)
    29         {
    30             int hashAddress = data % 13;
    31             //不等于0时,说明产生了冲突,这时用开放寻址法中的线性探测再散列
    32             while (hash[hashAddress] != 0)
    33             {
    34                 hashAddress = (++hashAddress) % 13;
    35             }
    36             //实现插入功能
    37             hash[hashAddress] = data;
    38         }
    39         static void Main(string[] args)
    40         {
    41             //创建hash
    42             for (int i = 0; i < list.Count; i++)
    43             {
    44                 InsertHash(hash, hashlength, list[i]);
    45             }
    46             Console.WriteLine("Hash数据:"+string.Join(",",hash));
    47             while (true)
    48             {
    49                 Console.WriteLine("
    请输入要查找的数字:");
    50                 int key = int.Parse(Console.ReadLine());
    51                 var index = SearchHash(key,hashlength,hash);
    52                 if (index == -1)
    53                     Console.WriteLine("不好意思啦,主人,我没找到这个值:" + key);
    54                 else
    55                     Console.WriteLine("主人,找到你要找到值"+key+"位置是:"+index);
    56 
    57             }
    58         }
    59     }
    60 }
    View Code

    数据库的索引,说实话,在这之前,并不知道数据库的索引要怎样去建立。

    数据库的索引其实是主键建立索引,方便我们在海量数据中查找。

    索引查找时常用的三个术语

    1,  主表,要查找的对象

    2,  索引项,一般会用函数将一个主表划分成几个子表,每个子表建立一个索引,这个索引就是索引项

    3,  索引项的集合是索引表

    一般的索引项包含了三种内容:index,start,length

    一:index,索引指向主表的关键字

    二:start,index在主表中的位置

    三:length,字表的区间长度

    代码:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 
     6 namespace Index
     7 {
     8     class Program
     9     {
    10         class IndexItem
    11         {
    12             public int index;
    13             public int start;
    14             public int length;
    15         }
    16         //学生表
    17         static int[] students ={
    18                            101,102,103,104,105,0,0,0,0,0,
    19 201,202,203,204,0,0,0,0,0,0,
    20 301,302,303,0,0,0,0,0,0,0};
    21         //学生索引表
    22         static IndexItem[] indexItem={
    23                new IndexItem(){index=1,start=0,length=5},
    24                 new IndexItem(){index=2,start=10,length=4}, 
    25                 new IndexItem(){index=3,start=20,length=3}};                     //查找数据
    26         public static int indexSearch(int key)
    27         {
    28             IndexItem item = null;
    29             var index = key / 100;
    30             //先找到索引
    31             for (int i = 0; i < indexItem.Count();i++)
    32             {
    33                 if (indexItem[i].index == index)
    34                 {
    35                     item = new IndexItem() { start=indexItem[i].start,length=indexItem[i].length};
    36                     break;
    37                 }
    38             }
    39             //如果索引为空,则在索引表中查找失败
    40             if (item == null)
    41                 return -1;
    42             for (int i = item.start; i < item.start + item.length; i++)
    43             {
    44                 if (students[i] == key)
    45                 {
    46                     return i;
    47                 }
    48             }
    49             //没找到时,返回-1
    50             return -1;
    51         }
    52         //插入数据
    53         public static int insert(int key)
    54         {
    55             IndexItem item = null;
    56             var index = key / 100;
    57             int i=0;
    58             for (i = 0; i < indexItem.Count(); i++)
    59             {
    60                 if (indexItem[i].index == index)
    61                 {//找到索引
    62                     item = new IndexItem()                              {
    63                         start=indexItem[i].start,
    64                         length=indexItem[i].length
    65                     };
    66                     break;
    67                 }
    68             }
    69             if (item == null)
    70                 return -1;
    71             students[item.start + item.length] = key;
    72             indexItem[i].length++;
    73             return 1;
    74         }
    75         static void Main(string[] args)
    76         {
    77             Console.WriteLine("原数据为:"+string.Join(",",students));
    78             int value = 205;
    79             Console.WriteLine("
    插入数据"+value);
    80             var index = insert(value);
    81             if (index == 1)
    82             {
    83                 Console.WriteLine("
    插入后数据:"+string.Join(",",students));
    84                 Console.WriteLine("
    数据元素205在数组中的位置为" + indexSearch(205));
    85             }
    86             Console.ReadLine();
    87         }
    88     }
    89 }
    View Code
    作者:wj704    出处:http://www.cnblogs.com/wj204/   
  • 相关阅读:
    如何找回未保存过的 Excel 文件?
    js 下关于json的销毁和添加
    width:100%和width:auto区别
    在ie6下的png图片的兼容问题
    关于input=file的用法
    div+Css绝对定位(absolute)和相对定位(relative)的总结
    onmouseenter和onmouseleave的兼容性问题
    ckfinder的配置使用
    破解ckfinder2.3 去除版本号和标题提示
    jQuery制作图片的等比例缩放
  • 原文地址:https://www.cnblogs.com/wj204/p/3365619.html
Copyright © 2020-2023  润新知