数据结构总复习(查找)

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

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("请输入元素的总个数:\n");

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("输入各元素的值:\n");

29     for(int i=0;i<n;i++,b++)

30         scanf("%d",b);

31     printf("请输入要查找的值:\n");

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("请输入元素的总个数:\n");

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("输入各元素的值:\n");

34     for(int i=0;i<n;i++,b++)

35         scanf("%d",b);

36     printf("请输入要查找的值:\n");

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("------------\n");

148             //查找一个节点

149             Console.WriteLine("在二叉树中是否包含:"+SearchBST(bstree,10));

150             Console.Write("------------\n");

151             bool isExcute = false;

152             InsertBST(bstree,20,ref isExcute);

153             Console.WriteLine("插入到二叉树,中序遍历后:");

154             LDR_BST(bstree);

155             Console.Write("------------\n");

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("\n请输入要查找的数字:");

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("\n插入数据"+value);

80             var index = insert(value);

81             if (index == 1)

82             {

83                 Console.WriteLine("\n插入后数据:"+string.Join(",",students));

84                 Console.WriteLine("\n数据元素205在数组中的位置为" + indexSearch(205));

85             }

86             Console.ReadLine();

87         }

88     }

89 }
View Code

 

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