我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C#怎么使用符号表实现查找算法

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C#怎么使用符号表实现查找算法

今天小编给大家分享一下C#怎么使用符号表实现查找算法的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

高效检索海量信息(经典查找算法)是现代信息世界的基础设施。我们使用符号表描述一张抽象的表格,将信息(值)存储在其中,然后按照指定的键来搜索并获取这些信息。键和值的具体意义取决于不同的应用。符号表中可能会保存很多键和很多信息,因此实现一张高效的符号表是很重要的任务。

符号表有时被称为字典,有时被称为索引。

1.符号表

符号表是一种存储键值对的数据结构,支持两种操作:插入(put),即将一组新的键值对存入表中;查找(get),即根据给定的键得到相应的值。符号表最主要的目的就是将一个健和一个值联系起来。

构造符号表的方法有很多,它们不光能够高效地插入和查找,还可以进行其他几种方便的操作。要实现符号表,首先要定义其背后的数据结构,并指明创建并操作这种数据结构以实现插入,查找等操作所需的算法。

API

    public interface ISymbolTables<Key,Value> where  Key : IComparable    {        int CompareCount { get; set; }        /// <summary>        /// 将键值对存入表中(若值未空则将键key从表中删除)        /// </summary>        /// <param name="key"></param>        /// <param name="value"></param>        void Put(Key key, Value value);        /// <summary>        /// 获取键 key 对应的值(若键不存在则返回 null)        /// </summary>        /// <param name="key"></param>        /// <returns></returns>        Value Get(Key key);        /// <summary>        /// 从表中删去键 key        /// </summary>        /// <param name="key"></param>        void Delete(Key key);        /// <summary>        /// 键 key 是否在表中存在        /// </summary>        /// <param name="key"></param>        /// <returns></returns>        bool Contains(Key key);        /// <summary>        /// 表是否未空        /// </summary>        /// <returns></returns>        bool IsEmpty();        /// <summary>        /// 表中的键值对数量        /// </summary>        /// <returns></returns>        int Size();        /// <summary>        /// 表中所有键的集合        /// </summary>        /// <returns></returns>        IEnumerable<Key> Keys();        /// <summary>        /// 最小的键        /// </summary>        /// <returns></returns>        Key Min();        /// <summary>        /// 最大的键        /// </summary>        /// <returns></returns>        Key Max();        /// <summary>        /// 小于等于 key 的键        /// </summary>        /// <param name="key"></param>        /// <returns></returns>        Key Floor(Key key);        /// <summary>        /// 大于等于 key 的键        /// </summary>        /// <param name="key"></param>        /// <returns></returns>        Key Ceilling(Key key);        /// <summary>        ///小于 key 的键的数量(key 的排名)        /// </summary>        /// <param name="key"></param>        /// <returns></returns>        int Rank(Key key);        /// <summary>        ///  排名为 k 的键        /// </summary>        /// <param name="k"></param>        /// <returns></returns>        Key Select(int k);        /// <summary>        /// 删除最小的键        /// </summary>        void DeleteMin();        /// <summary>        /// 删除最大的键        /// </summary>        void DeleteMax();        /// <summary>        /// [lo ... hi]之间的键的数量        /// </summary>        /// <param name="lo"></param>        /// <param name="hi"></param>        /// <returns></returns>        int Size(Key lo,Key hi);        /// <summary>        /// [lo ... hi]之间的键        /// </summary>        /// <param name="lo"></param>        /// <param name="hi"></param>        /// <returns></returns>        IEnumerable<Key> Keys(Key lo, Key hi);    }

基本实现:

    /// <summary>    /// 符号表基类    /// </summary>    /// <typeparam name="Key"></typeparam>    /// <typeparam name="Value"></typeparam>    public class BaseSymbolTables<Key, Value>: ISymbolTables<Key, Value>        where Key : IComparable    {        public int CompareCount { get; set; }        /// <summary>        /// 将键值对存入表中(若值未空则将键key从表中删除)        /// </summary>        /// <param name="key"></param>        /// <param name="value"></param>        public virtual void Put(Key key, Value value)        {         }        /// <summary>        /// 获取键 key 对应的值(若键不存在则返回 null)        /// </summary>        /// <param name="key"></param>        /// <returns></returns>        public virtual Value Get(Key key)        {            return default(Value);        }        /// <summary>        /// 从表中删去键 key        /// </summary>        /// <param name="key"></param>        public void Delete(Key key)        {                    }        /// <summary>        /// 键 key 是否在表中存在        /// </summary>        /// <param name="key"></param>        /// <returns></returns>        public bool Contains(Key key)        {            return false;        }        /// <summary>        /// 表是否未空        /// </summary>        /// <returns></returns>        public bool IsEmpty()        {            return Size()==0;        }        /// <summary>        /// 表中的键值对数量        /// </summary>        /// <returns></returns>        public virtual int Size()        {            return 0;        }        /// <summary>        /// 表中所有键的集合        /// </summary>        /// <returns></returns>        public virtual IEnumerable<Key> Keys()        {            return new List<Key>();        }        /// <summary>        /// 最小的键        /// </summary>        /// <returns></returns>        public virtual Key Min()        {            return default(Key);        }        /// <summary>        /// 最大的键        /// </summary>        /// <returns></returns>        public virtual Key Max()        {            return default(Key);        }        /// <summary>        /// 小于等于 key 的键        /// </summary>        /// <param name="key"></param>        /// <returns></returns>        public virtual Key Floor(Key key)        {            return default(Key);        }        /// <summary>        /// 大于等于 key 的键        /// </summary>        /// <param name="key"></param>        /// <returns></returns>        public virtual Key Ceilling(Key key)        {            return default(Key);        }        /// <summary>        ///小于 key 的键的数量(key 的排名)        /// </summary>        /// <param name="key"></param>        /// <returns></returns>        public virtual int Rank(Key key)        {            return 0;        }        /// <summary>        ///  排名为 k 的键        /// </summary>        /// <param name="k"></param>        /// <returns></returns>        public virtual Key Select(int k)        {            return default(Key);        }        /// <summary>        /// 删除最小的键        /// </summary>        public virtual void DeleteMin()        {        }        /// <summary>        /// 删除最大的键        /// </summary>        public virtual void DeleteMax()        {        }        /// <summary>        /// [lo ... hi]之间的键的数量        /// </summary>        /// <param name="lo"></param>        /// <param name="hi"></param>        /// <returns></returns>        public virtual int Size(Key lo, Key hi)        {            return 0;        }        /// <summary>        /// [lo ... hi]之间的键        /// </summary>        /// <param name="lo"></param>        /// <param name="hi"></param>        /// <returns></returns>        public virtual IEnumerable<Key> Keys(Key lo, Key hi)        {            return new List<Key>();        }    }

2.有序符号表

典型的应用程序中,键都是IComparable 对象,因此可以使用 a.CompareTo( b ) 来比较 a 和 b 两个键。符号表保持键的有序性,可以扩展它的API,根据键的相对位置定义更多实用操作。例如,最大和最小的键。

排名(Rank 方法)和选择 (Select 方法)

检查一个新的键是否插入合适位置的基本操作是排名(Rank,找出小于指定键的键的数量)和选择(Select,找出排名为 k 的键)。对于 0 到 Size()-1 的所有 i 都有 i == Rank( Select(i) ),且所有的键都满足 key == Select( Rank( key ) ) 。

键的等价性

IComparable 类型中 CompareTo 和 Equals 方法是一致的,但为了避免任何潜在的二义性,这里只是用a.CompareTo( b ) == 0 来判断 a 和 b 是否相等。

成本模型

查找的成本模型:在符号表的实现中,将比较的次数作为成本模型。在内循环不进行比较的情况下,使用数组的访问次数。

符号表实现的重点在于其中使用的数据结构和 Get() , Put() 方法。

3.无序链表中的顺序查找

符号表中使用的数据结构的一个简单选择是链表,每个结点存储一个键值对。

Get 方法的实现即为遍历链表,用Equals 方法比较需要查找的键和每个结点中键。如果匹配就返回相应的值,否则返回 null。Put 方法的实现也是遍历,如果匹配就更新相应的值,否则就用给定的键值对创建一个新的结点并将其插入链表的开头。这种方法称为顺序查找。

    /// <summary>    /// 顺序查找    /// </summary>    /// <typeparam name="Key"></typeparam>    /// <typeparam name="Value"></typeparam>    public  class SequentialSearchST<Key,Value>:BaseSymbolTables<Key, Value>        where Key : IComparable    {                private Node First;        private class Node        {            public Key key;            public Value value;            public Node next;            public Node(Key _key,Value _value,Node _next)            {                key = _key;                value = _value;                next = _next;            }        }        public override Value Get(Key key)        {            for (Node x = First; x != null; x = x.next)            {                if (key.Equals(x.key))                    return x.value;            }            return default(Value);        }        public override void Put(Key key, Value value)        {            for (Node x = First; x != null; x = x.next)            {                CompareCount++;                if (key.Equals(x.key))                {                    x.value = value;                    return;                }            }            First = new Node(key,value,First);        }    }

这里我们使用一个字符串数组来测试上面的算法,键是数组中的值,值是插入的索引:

string[] strs = new string[] { "S", "E", "A", "R", "C", "H", "E", "X", "A", "M", "P", "L", "E" };

下面是顺序查找的索引用例的轨迹:

分析符号表算法比排序算法更困难,因为不同的用例所进行的操作序列各不相同。常见的情形是虽然查找和插入的使用模式是不可预测的,但它们的使用肯定不是随机的。因此我们主要研究最坏情况下的性能。我们使用命中表示一次成功的查找,未命中表示一次失败的查找。

C#怎么使用符号表实现查找算法

在含有 N 对键值的基于链表的符号表中,未命中的查找和插入操作都需要 N 次比较。命中的查找在最坏情况下需要 N 次比较。特别地,向一个空表中插入 N 个不同的键需要 ~ N^2 /2 次比较。

查找一个已经存在的键并不需要线性级别的时间。一种度量方法是查找表中的每个键,并将总时间除以 N 。在查找表中每个键的可能性都相同的情况下,这个结果就是一次查找平均所需的比较次数。称它为随机命中。由上面的算法可以得到平均比较次数为 ~N/2: 查找第一个键需要比较一次,查找第二个键需要比较两次 ...... 平均比较次数为(1+2+3.....+N)/ N = (N+1)/2。

这证明基于链表的实现以及顺序查找是低效的。

4.有序数组中的二分查找

有序符号表API的实现使用的数据结构是一对平行的数组,一个存储键一个存储值。下面的代码保证数组中IComparable 类型的键有序,然后使用数组的索引来高效地实现 Get 和其他操作。

下面算法的核心是 Rank 方法(它使用二分查找的算法),它返回表中小于给定键的键的数量。对于 Get 方法,只要给定的键存在于表中就返回,否则返回空。

Put 方法,只要给定的键存在于表中,Rank 方法就能够精确告诉我们它的为并去更新,以及当键不存在时我们也能直到将键存储到什么位置。插入键值对时,将更大的键和值向后移一格,并将给定的键值对分别插入到数组。

    public class BinarySearchST<Key,Value> : BaseSymbolTables<Key, Value>        where Key : IComparable    {        private Key[] keys;        private Value[] vals;        private int N;        public BinarySearchST(int capacity)        {            keys = new Key[capacity];            vals = new Value[capacity];        }        public override int Size()        {            return N;        }        public override Value Get(Key key)        {            if (IsEmpty())                return default(Value);            int i = Rank(key);            if (i < N && keys[i].CompareTo(key) == 0)                return vals[i];            else                return default(Value);        }        public override int Rank(Key key)        {            int lo = 0, hi = N - 1;            while (lo <= hi)            {                int mid = lo + (hi-lo) / 2;                CompareCount++;                int cmp = key.CompareTo(keys[mid]);                if (cmp < 0)                    hi = mid - 1;                else if (cmp > 0)                    lo = mid + 1;                else                    return mid;            }            return lo;        }        public override void Put(Key key, Value value)        {            int i = Rank(key);            if (i < N && keys[i].CompareTo(key) == 0)            {                vals[i] = value;                return;            }            for (int j = N; j > i; j--)            {                keys[j] = keys[j-1];                vals[j] = vals[j-1];            }            keys[i] = key;            vals[i] = value;            N++;        }        public override Key Min()        {            return keys[0];        }        public override Key Max()        {            return keys[N-1];        }        public override Key Select(int k)        {            return keys[k];        }        public override Key Ceilling(Key key)        {            int i = Rank(key);            return keys[i];        }        public override IEnumerable<Key> Keys()        {            return keys;        }    }

下面是该算法的用例移动轨迹:

C#怎么使用符号表实现查找算法

对二分查找的分析

Rank 方法的递归实现使用了二分查找,二分查找比顺序查找快很多。在 N 个键的有序数组中进行二分查找最多需要 (lgN + 1)次比较。

尽管该算法能够保证查找所需的时间是对数级别的,但 Put 方法还是太慢,需要移动数组。对于随机数组,构造一个基于有序数组的符号表所需访问数组的次数是数组长度的平方级别。

向大小为 N 的有序数组中插入一个新的键值对在最坏情况下需要访问 ~2N 次数组,因此向一个空符号表中插入 N 个元素在最坏情况下需要访问 ~N^2 次数组。

对于一个静态表(不允许插入)来说,将其在初始化时就排序是值得的。下面是符号表简单实现的总结:

算法

最坏情况下的成本

(N 次插入后)

平均情况下的成本

(N 次随机插入后)

是否支持有序性相关的操作
查找插入查找插入
顺序查找(无序链表)NNN/2N
二分查找(有序数组)lgN2NlgNN

以上就是“C#怎么使用符号表实现查找算法”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C#怎么使用符号表实现查找算法

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C#怎么使用符号表实现查找算法

今天小编给大家分享一下C#怎么使用符号表实现查找算法的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。高效检索海量信息(经典查找
2023-06-30

C#二分查找算法怎么用

这篇“C#二分查找算法怎么用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C#二分查找算法怎么用”文章吧。1、定义:折半搜索
2023-06-30

php二分查找算法怎么实现

PHP实现二分查找算法的步骤如下:确定要查找的数组和目标值。定义一个函数,传入查找的数组、目标值以及数组的起始位置和结束位置作为参数。在函数内部,计算数组的中间位置,并将中间位置的值与目标值进行比较。如果中间位置的值等于目标值,则直接
php二分查找算法怎么实现
2024-03-15

怎么使用C++实现Dijkstra算法

本篇内容介绍了“怎么使用C++实现Dijkstra算法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!具体代码1.graph类graph类用于
2023-07-02

C语言折半查找法怎么使用

这篇文章主要介绍了C语言折半查找法怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言折半查找法怎么使用文章都会有所收获,下面我们一起来看看吧。折半查找法仅适用于对已有顺序的数组、数据进行操作!!!(从
2023-07-02

怎么使用python正则表达式查找字符串

使用Python的re模块来使用正则表达式查找字符串。首先,导入re模块:```pythonimport re```然后,定义一个正则表达式模式:```pythonpattern = r"正则表达式模式"```接下来,使用re模块的find
2023-08-18

C++运算符重载方法怎么使用

本篇内容介绍了“C++运算符重载方法怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!概念C++为了增强代码的可读性引入了运算符重载,运
2023-06-30

Java中常见的查找算法与排序算法怎么使用

这篇文章主要介绍了Java中常见的查找算法与排序算法怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java中常见的查找算法与排序算法怎么使用文章都会有所收获,下面我们一起来看看吧。1. 基本查找也叫做顺
2023-07-05

C语言回文字符串算法怎么实现

实现回文字符串算法的一种常见方法是通过比较字符串的首尾字符来判断是否为回文。具体步骤如下:定义两个指针,一个指向字符串的首字符,一个指向字符串的尾字符。通过循环,依次比较首尾字符是否相等,如果相等则继续比较下一对字符,如果不相等则不是回文
C语言回文字符串算法怎么实现
2024-02-29

C#图表算法之最短路径怎么实现

本篇内容主要讲解“C#图表算法之最短路径怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#图表算法之最短路径怎么实现”吧!从一个顶点到达另一个顶点的成本最小的路径。我们采用一个一般性的模
2023-06-30

怎么使用C语言实现Hash表

这篇“怎么使用C语言实现Hash表”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么使用C语言实现Hash表”文章吧。什么是
2023-07-05

怎么在java项目中实现一个二叉查找树算法

今天就跟大家聊聊有关怎么在java项目中实现一个二叉查找树算法,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。具体内容如下package 查找;import edu.princeton
2023-05-31

怎么使用C++动态规划算法实现矩阵链乘法

这篇文章主要介绍“怎么使用C++动态规划算法实现矩阵链乘法”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么使用C++动态规划算法实现矩阵链乘法”文章能帮助大家解决问题。问题描述:给定n个矩阵的链<
2023-07-02

C#算法怎么实现无重复字符的最长子串

这篇文章主要介绍“C#算法怎么实现无重复字符的最长子串”,在日常操作中,相信很多人在C#算法怎么实现无重复字符的最长子串问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#算法怎么实现无重复字符的最长子串”的疑
2023-06-26

怎么在Java中利用二叉查找树算法实现一个排序功能

这期内容当中小编将会给大家带来有关怎么在Java中利用二叉查找树算法实现一个排序功能,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。具体如下:/** * 无论排序的对象是什么,都要实现Comparable接
2023-05-31

怎么在java中使用mongodb实现多表联查

这期内容当中小编将会给大家带来有关怎么在java中使用mongodb实现多表联查,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。多表联查的查询语句:此处使用的为mongodb的robo3t可视化工具,先说下
2023-06-14

怎么使用PHP实现C语言中的异或加密算法

本篇内容介绍了“怎么使用PHP实现C语言中的异或加密算法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、异或加密算法简介异或加密算法是一种
2023-07-05

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录