数据结构总复习(查找)

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

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/   
原文地址:https://www.cnblogs.com/wj204/p/3365619.html