顺序查找和二分查找算法多种编程语言实现(修订)
查找,也可称检索,是在多个信息中寻找一个特定的信息元素,在此介绍顺序查找和二分查找算法的多种编程语言实现。给出C++代码、Java代码、Python代码和JavaScript代码。
预备知识:数组
先简要介绍本文中用到的各种编程语言一维数组知识。
数组能够一次存放一个以上的值。
C++数组
要声明数组,请定义变量类型,数组名称后跟方括号,方括号内指定它应存储的元素数。声明数组变量时,可以初始化值,放在大括号内,多个值用逗号分隔,如:
string cars[ ] = {"Volvo", "BMW", "Ford", "Mazda"};
int myNum[ ] = {10, 20, 30};
数组索引以0开头:[0]是第一个元素,[1] 是第二个元素。
使用C/C++中的运算符(操作符)sizeof,可以获取数组元素的个数,如sizeof(cars)/sizeof(cars[0]) 的值是4。【想进一步了解利用sizeof获取数组元素的个数,可见 https://juejin.cn/post/7135987485221322783】但需要注意如下面例子的情况,countA和countB值不同,countA值正确,而countB值不对。
#include <iostream>
using namespace std;
//void f(string arr[]) 可改为 void f(string *arr)
void f(string arr[]){
int countB = sizeof(arr)/sizeof(arr[0]); //countB是多少? 不是期望值
cout<<"countB="<<countB<<endl;
}
int main(){
string cars[ ] = {"Volvo", "BMW", "Ford", "Mazda"};
int countA= sizeof(cars)/sizeof(cars[0]); //countA是期望的4
cout<<"countA="<<countA<<endl;
f(cars);
return 0;
}
原因?是因为一旦你将一个数组传递给这些函数中的任何一个,它就变成了指针类型——所谓数组会退化为一个指针,所以sizeof(arr)会给出指针的大小,而不是数组! 参见https://qa.1r1g.com/sf/ask/338773851/
对于上面的代码,如果想在f函数中使用countA的值,可定义外部变量(全局变量):
#include <iostream>
using namespace std;
int count; //外部变量(全局变量
//void f(string arr[]) 可改为 void f(string *arr)
void f(string arr[]){
int countB = count; //
cout<<"countB="<<countB<<endl;
}
int main(){
string cars[] = {"Volvo", "BMW", "Ford", "Mazda"};
int countA= sizeof(cars)/sizeof(cars[0]); //countA是期望的4
cout<<"countA="<<countA<<endl;
count= countA;
f(cars);
return 0;
}
Java 数组
要声明数组,请使用方括号定义变量类型。声明数组变量时,可以初始化值,放在大括号内,多个值用逗号分隔,如:
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
int[] myNum = {10, 20, 30, 40};
使用数组属性length来获取数组元素的个数,如cars. length的值是4。
Python“数组”
请注意,Python 没有内置对数组的支持,但可以使用 Python 列表代替。如:
cars= ["Volvo", "BMW", "Ford", "Mazda"]
myNum = [10, 20, 30]
索引以0开头:[0]是第一个元素,[1] 是第二个元素。
使用 len() 函数来返回列表的长度(列表中的元素数量),如len(cars)的值是4。
JavaScript数组
JavaScript 数组特点
JavaScript数组在定义时不需要指定数据类型,可以可以同时不同数据类型的数据。
var|let cars = ["Volvo", "BMW", "Ford", "Mazda"];
var|let myNum = [10, 20, 30];
其中var、let这两个关键字都能用来声明变量。最大的区别在于作用域中,并且let不存在变量提升,而var存在变量提升。
可以使用length属性获得数组元素的个数,如len(cars)的值是4。
顺序查找
顺序查找也称为线形查找,属于无序查找算法。
顺序查找适合于存储结构为顺序存储或链接存储的线性表。
基本思想:从数据序列的一端开始,顺序扫描,依次将扫描到的元素与查找关键字(给定查找值)相比较,直到查找到或至查找结束没发现这样的元素。
假设要在10,34,86,8,15,56,45,67中,顺序找56和20
查找成功(找到)输出其位置索引(下标),未查到输出-1
【注:多数编程语言一维数组的位置索引(下标)从0开始,如上述数据排在第6位的56,其位置索引是5】
C++代码
#include <iostream>
using namespace std;
int len; //记录元素个数
/**
* 线性查找算法
* @param arr 查找的数组
* @param target 查找的元素
* return 返回所在位置的下标
*/
int liner_search(int arr[], int target) {
for (int i = 0; i < len; i++){
if (arr[i] == target) {
return i; // 返回数组下标
}
}
return -1; // 整个循环结束还没找到数字下标,返回-1
}
int main(){
int arr[] = { 10,34,86,8,15,56,45,67 }; // 创建数组
len = sizeof(arr) / sizeof(arr[0]) ; // 计算数组元素个数
cout << liner_search(arr, 56)<< endl;
cout << liner_search(arr, 20)<< endl;
return 0;
}
Java代码
public class SeqSearch {
public static void main(String[] args) {
int[] arr = {10,34,86,8,15,56,45,67};
System.out.println(seqSearch(arr, 56));
System.out.println(seqSearch(arr, 20));
}
/**
* 线性查找算法
* @param arr 查找的数组
* @param target 查找的元素
* return 返回所在位置的下标
*/
public static int seqSearch(int[] arr,int target){
for (int i = 0; i < arr.length; i++) {
if (arr[i] == target){
return i;
}
}
//返回-1表示没找到
return -1;
}
}
Python代码
# 线性查找算法
# @param data 查找的列表数组
# @param key 查找的元素
# return 返回所在位置的下标
def linear_search(data,key):
lens = len(data)
for i in range(lens):
if data[i] == key:
return i # 找到返归下标
return -1 # 未找到返归-1
values = [10,34,86,8,15,56,45,67] #数据列表
print(linear_search(values,56))
print(linear_search(values,20))
JavaScript代码
/**
* 线性查找算法
* @param arr 查找的数组
* @param target 查找的元素
* return 返回所在位置的下标
*/
function seqSearch(arr,target){
for (let i = 0; i < arr.length; i++) {
if (arr[i] == target){
return i;
}
}
return -1; //返回-1表示没找到
}
arr = [10,34,86,8,15,56,45,67];
console.log(seqSearch(arr, 56))
console.log(seqSearch(arr, 20))
二分查找(Binary Search)
二分查找(Binary Search)算法,也叫折半查找算法,元素必须是有序的,如果是无序的则要先进行排序操作。
基本思想:元素必须是有序的,假设表中元素是按升序排列,将表中间位置元素与查找关键字(给定查找值)比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置元素大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到查找到或至查找结束没发现这样的元素。
假设要在10, 20, 30, 40, 50, 60, 70中,二分查找60和90
查找成功(找到)输出其位置索引(下标),未查到输出-1
C++代码
#include <iostream>
using namespace std;
int high; //记录高端元素下标
/**
* 二分法查找算法
* @param Arr 查找的数组
* @param k 查找的元素
* return 返回所在位置的下标
*/
int SearchK(int Arr[],int k){
int mid; //记录中间位置
int low =0; //低端元素下标
while (low<high){
mid = (low + high) / 2;
if (Arr[mid] ==k)
return mid + 1;
else
{
if (Arr[mid] < k)//右边查找
low = mid + 1;
else
high = mid - 1;
}
}
return -1;//没找到返回-1
}
int main(){
int p[] = { 10, 20, 30, 40, 50, 60, 70 };
high = sizeof(p) / sizeof(p[0]) -1; // 计算高端元素下标
cout<<SearchK(p, 60)<<endl;
cout << SearchK(p, 90)<<endl;
return 0;
}
Java代码
public class BinarySearch {
public static void main(String[] args) {
int[] p = { 10, 20, 30, 40, 50, 60, 70 };
System.out.println(SearchK(p, 60));
System.out.println(SearchK(p, 90));
}
/**
* 二分法查找算法
* @param Arr 查找的数组
* @param k 查找的元素
* return 返回所在位置的下标
*/
public static int SearchK(int[] Arr,int k){
int mid; //记录中间位置
int low=0; //低端元素下标
int high = Arr.length-1; //高端元素下标
while (low<high)
{
mid = (low + high) / 2;
if (Arr[mid] ==k)
return mid + 1;
else
{
if (Arr[mid] < k)//右边查找
low = mid + 1;
else
high = mid - 1;
}
}
return -1;//没找到返回-1
}
}
Python代码
# 二分法查找算法
# @param Arr 查找的数组
# @param k 查找的元素
# return 返回所在位置的下标
def SearchK(Arr,k):
low = 0 # 低端元素下标
high =len(Arr) - 1 #高端元素下标
while low<high:
mid = (low + high) // 2 #记录中间位置
if Arr[mid] ==k:
return mid + 1
else:
if Arr[mid] < k: #右边查找
low = mid + 1
else:
high = mid - 1
return -1 #没找到返回-1
p = [ 10, 20, 30, 40, 50, 60, 70 ] #数据列表
print(SearchK(p,60))
print(SearchK(p,90))
JavaScript代码
/**
* 二分法查找算法
* @param Arr 查找的数组
* @param k 查找的元素
* return 返回所在位置的下标
*/
function SearchK(Arr,k)
{
let mid; //记录中间位置
let low =0; //低端元素下标
let high =Arr.length-1; //高端元素下标
while (low<high)
{
mid = (low + high) / 2;
if (Arr[mid] ==k)
return mid + 1;
else
{
if (Arr[mid] < k)//右边查找
low = mid + 1;
else
high = mid - 1;
}
}
return -1;//没找到返回-1
}
p = [ 10, 20, 30, 40, 50, 60, 70 ];
console.log(SearchK(p, 60));
console.log(SearchK(p, 90))
OK!