1,顺序查找
顺序查找又称线性查找,它对顺序表和链表都适用。
(1)以下给出相关函数
1 typedef struct{ 2 ElemType *elem; //元素存储空间地址,建表时按实际长度分配,0号单元留空 3 int TableLen; //表的长度 4 }SSTable; 5 int Search_Seq(SSTable ST,ElemType key) 6 { 7 ST.elem[0]=key; //把要查找的关键字放在0号位置,称“哨兵” 8 for(int i=ST.TableLen;ST.elem!=key;i--) //从后往前找 9 { 10 return i; //若表中不存在关键字为key的元素,将查找i=0时退出循环 11 } 12 }
在上述算法中,将ST.elem[0]称为“哨兵”。引入它的目的是使得Search_Seq内的循环不必判断数组是否会越界。因为满足i=0时,循环一定会跳出。除此之外,引入“哨兵”可以避免很多不必要的判断语句,从而提高算法的执行效率。
(2)算法效率分析
当每个元素查找概率相同时,平均查找长度ASL=(n+1)/2, 查找不成功时,需要比较整个顺序表,所以比较次数时(n+1)次,从而顺序查找不成功的平均查找长度为(n+1)。
2.有序表的顺序查找(假设从小到大排列)
有序表的顺序查找成功的平均查找长度与一般的线性表一样,即(n+1)/2.
当查找失败时,待查找的元素为key,当查找第i个元素时,发现第i个元素的对应的关键字小于key,但第i+1个元素对应的关键字大于key,这时就可以返回查找失败的信息。
查找失败的平均查找长度为ASL=n/2+n/(n+1).
3.折半查找
前提:折半查找仅适用于有序的顺序表。
折半查找原理:将给定的key与中间元素比较,直到查到要找的元素。
以下是相关函数
1 int Binary_Search(SeqList L,ElemType key){ 2 int low=0,high=L.TableLen-1,mid;//low指向表头,high指向表尾,mid中间值 3 while(low<=high) 4 { 5 mid=(low+high)/2; 6 if(L.elem[mid]==key) //中间值等于要查找元素 7 return mid; 8 else if(L.elem[mid]<key) //要查找元素在中间值右边 9 low=mid+1; 10 else 11 hign=mid-1; //要查找元素在中间值左边 12 } 13 }
查找成功的时间复杂度为log2n,平均情况下比顺序查找效率高一些。
引入一个思考题,我们已经知道顺序查找成功的时间复杂度为(n+1)/2,折半查找的时间复杂度为,log2n那么折半查找的效率一定比顺序查找高吗?
答案是否定的,假设我们查找的元素在顺序表的第一个位置,那么顺序查找只需要查找1次就可以,二折半查找需要很多次,时间复杂度只是查找的平均时间复杂度的反映。