查找算法(顺序查找、二分查找、差值查找、斐波那契查找、树表查找、分块查找、哈希查找)

1.顺序查找:从数据集合的一端开始逐个查找比较,直到找到目标值或遍历完数据集合。适用于数量较小或无序的情况。

using System;

namespace SearchAlgorithm
{
    internal class Program
    {
        static int SequentialSearch(int[] arr,int key)
        {
            for(int i=0; i < arr.Length; i++)
            {
                if(arr[i] == key)
                {
                    return i;
                }
            }
            return -1;
        }
        static void Main(string[] args)
        {
            int[] arr = {4,3,-2,8,1};
            Console.WriteLine(arr[SequentialSearch(arr, 8)]);
        }
    }
}

2.二分查找:基于数据有序(升序或降序)的情况查找。从数据集合中间的元素开始查找比较,返回中间元素的索引。如果目标值小于中间值,以中间值的左端(升序)或右端(降序)为新的数据集合;如果目标值大于中间值,则相反;选出的新的数据集合又从中间值查找比较,如此往复。

using System;

namespace SearchAlgorithm
{
    internal class Program
    {
        static int BinarySearch(int[] arr,int key)
        {
            int left = 0;
            int right = arr.Length-1;
            while (left <= right)
            {
                int mid = (left + right) / 2;//计算中间值的索引
                if(arr[mid] == key)
                {
                    return mid;
                }
                else if (arr[mid]<key)
                {
                    left = mid+1;
                }
                else
                {
                    right = mid-1;
                }
            }
            return -1;
        }
        static void Main(string[] args)
        {
            int[] arr = {1,3,5,8,10,13};//有序的前提
            Console.WriteLine(arr[BinarySearch(arr, 8)]);
        }
    }
}

3.差值查找:是对二分查找的优化,以按照差值比例去查找。当数据集合中的元素分布比较均匀时,差值查找的效率比较高;如果数据中的元素分布不均匀,比如出现大量重复或者分布不连续,则查找效率会比较低

using System;

namespace SearchAlgorithm
{
    internal class Program
    {
        static int InterpolationSearch(int[] arr,int key)
        {
            int low = 0;
            int high = arr.Length-1;
            while (low <= high)
            {
                int pos = low + (key - arr[low]) / (arr[high] - arr[low])*(high-low);
                if(arr[pos] == key)
                {
                    return pos;
                }
                else if (arr[pos]<key)
                {
                    low = pos+1;
                }
                else
                {
                    high = pos-1;
                }
            }
            return -1;
        }
        static void Main(string[] args)
        {
            int[] arr = {1,3,5,8,10,13};//有序的前提
            Console.WriteLine(InterpolationSearch(arr, 8)]);
        }
    }
}

4.斐波那契查找

using System;

namespace SearchAlgorithm
{
    internal class Program
    {
        static int[] Fibonacci(int n)
        {
            int[] f = new int[n + 1];
            f[0] = 0;
            f[1] = 1;
            for (int i = 2; i <= n; i++)
            {
                f[i] = f[i - 1] + f[i - 2];
            }
            return f;
        }
        static int FibonacciSearch(int[] arr, int key)
        {
            int n = arr.Length;
            int[] f = Fibonacci(n);//获取斐波那契数列
            int k = 0;//表示斐波那契分割数值的下标
            //获取斐波那契分割数值的下标
            while (n > f[k] - 1)
            {
                k++;
            }
            int[] temp = new int[f[k] - 1];
            //因为f[k]-1的值可能大于arr的长度,所以将arr的值复制到新的数组中
            Array.Copy(arr, temp, n);
            //填充适用arr数组最后的数填充temp,使它保持有序
            for (int i = n; i < f[k] - 1; i++)
            {
                temp[i] = arr[n - 1];
            }
            int left = 0;
            int right = n - 1;
            //适用while来找key
            while (left <= right)
            {
                int mid = left + f[k - 1] - 1;
                if (key < temp[mid])
                {
                    right = mid - 1;//继续向左边的元素查找
                    k--;//f[k-1]=f[k-2](左边)+f[k-3](右边);
                }
                else if (key > temp[mid])
                {
                    left = mid + 1;//继续向右边的元素查找
                    k -= 2;
                }
                else
                {
                    if (mid < n)
                    {
                        return mid;
                    }
                    else
                    {
                        return n - 1;
                    }
                }
            }
            return -1;
        }
        static void Main(string[] args)
        {
            int[] arr = { 1, 3, 5, 8, 10, 13 };//有序的前提
            Console.WriteLine(arr[FibonacciSearch(arr, 13)]);
        }
    }
}

084-尚硅谷-图解Java数据结构和算法-斐波那契查找代码实现.avi_哔哩哔哩_bilibili

5.树表查找

using System;

namespace SearchAlgorithm
{
    internal class Program
    {
        static TreeNode insert(TreeNode root, int data)//以递归的形式插入数据
        {
            if (root == null)
                return new TreeNode(data);
            if (data < root.data)
                root.left = insert(root.left, data);
            else if (data > root.data)
                root.right = insert(root.right, data);
            return root;
        }
        static bool TreeTableSearch(TreeNode root, int key)//递归查找
        {
            if (root == null)
                return false;
            if (root.data == key)
                return true;
            if (root.data > key)
                return TreeTableSearch(root.left, key);
            return TreeTableSearch(root.right, key);
        }
        static void Main(string[] args)
        {
            int[] arr = {1,3,5,8,10,13};
            TreeNode root = null;
            for(int i=0;i<arr.Length;i++)
            {
                root = insert(root, arr[i]);//向树中插入数据
            }
            if(TreeTableSearch(root,10))
            {
                Console.WriteLine("找到了");
            }
        }
    }
    class TreeNode
    {
        public int data;
        public TreeNode left, right;
        public TreeNode(int data)
        {
            this.data = data;
            left = right = null;
        }
    }
}

6.分块查找

using System;
using System.Collections.Generic;

namespace SearchAlgorithm
{
    internal class Program
    {
        static int blockSearch(int[] arr, int key, int blockSize)//基于块内无序,且块与块之间有序
        {
            int n = arr.Length;
            int blockCount = (int)Math.Ceiling((double)n / blockSize);//表示数组分块后的块的数量
            List<int[]> blocks = new List<int[]>();
            //将数组中的元素放入块数组中,再将块数组放入blocks链表中
            for (int i = 0; i < blockCount; i++)
            {
                int[] block = new int[blockSize];
                for (int j = 0; j < blockSize; j++)
                {
                    int index = i * blockSize + j;
                    if (index < n)
                        block[j] = arr[index];
                    else
                        break;
                }
                blocks.Add(block);
            }
            int blockIndex = -1;//记录key所在的块数组的索引
            //找到key所在的块数组
            for (int i = 0; i < blockCount; i++)
            {
                if (key <= blocks[i][blockSize - 1])
                {
                    blockIndex = i;
                    break;
                }
            }
            if (blockIndex == -1)
                return -1;
            int[] blockArr = blocks[blockIndex];//key所在的块数组
            //找到key再arr中的索引
            for (int i = 0; i < blockSize; i++)
            {
                if (blockArr[i] == key)
                    return blockIndex * blockSize + i;
            }
            return -1;
        }
        static void Main(string[] args)
        {
            int[] arr = {1,3,5,8,10,13};
            int blockSize = 3;
            Console.WriteLine(arr[blockSearch(arr, 10, blockSize)]);
        }
    }
}

【天勤考研】分块查找_哔哩哔哩_bilibili

7.哈希查找

using System;
using System.Collections.Generic;

namespace SearchAlgorithm
{
    internal class Program
    {
        static int HashValue(int x)//计算哈希值
        {
            return x % 10;
        }
        static void HashSearch(int[] arr,int key)
        {
            Dictionary<int, int> dict = new Dictionary<int, int>();//存储哈希值对应的数组元素
            //计算对应的数组元素的哈希值,并将哈希值和数组元素存储字典
            for (int i = 0; i < arr.Length; i++)
            {
                int index = HashValue(arr[i]);
                if (!dict.ContainsKey(index))
                    dict.Add(index, arr[i]);
                else // 如果该位置已经有元素,则使用开放地址法解决冲突
                {
                    while (dict.ContainsKey(index))
                        index = (index + 1) % 10;
                    dict.Add(index, arr[i]);
                }
            }
            int hash = HashValue(key); // 计算要查找的数组元素的哈希值
            if (dict.ContainsKey(hash))
            {
                if (dict[hash]==key)
                {
                    Console.WriteLine("找到了");
                }
            }
        }
        static void Main(string[] args)
        {
            int[] arr = {1,3,5,8,10,13};
            HashSearch(arr, 10);
        }
    }
}

 结语:合抱之木,生于毫末;九层之台,起于累土;千里之行,始于足下。

猜你喜欢

转载自blog.csdn.net/falsedewuxin/article/details/130298001
今日推荐