精华内容
下载资源
问答
  • 数据结构】顺序查找
    千次阅读
    2017-12-06 14:17:58
    利用顺序表查找数据。
    #include<stdio.h>
    #include<iostream>
    using namespace std; 
    
    #define LIST_INIT_SIZE  100//顺序表存储空间的初始分配量 
    #define OK 1
    #define ERROR 0
    #define LT(a,b) ((a)<=(b))
    
    
    typedef int KeyType;
    typedef int Status;
    typedef struct 
    {
    	KeyType key;
    }ElemType;
    
    typedef struct
    {
    	ElemType *elem;
    	int length;
    }SSTable;
    
    
    Status Init_Sq(SSTable &ST)//构造一个空的线性表 
    {
    	ST.elem=new ElemType[LIST_INIT_SIZE];
    	ST.length=0;
    	return OK;
    }
    
    Status Create_Sq(SSTable &ST,int n)//创建一个非空顺序表 
    {
    	int i;
    	if(n<0) 
    	return ERROR;
    	Init_Sq(ST);
        ST.length=n;
    	cout<<"请输入"<<n<<" 数字";
    	cout<<endl;
    	for (i=0;i<ST.length;i++)
    	{
        cin>>ST.elem[i].key;
        }
        return OK;	
    }
    
    Status Output_Sq(SSTable &ST)//输出顺序表 
    {
    	int i;
        cout<<"顺序表各元素为";
        for(i=0;i<ST.length;i++)
        cout<<ST.elem[i].key<<" ";
        cout<<endl;
        return OK;
    }
    
    int Search_Sq(SSTable ST,KeyType key)
    {
    	int i;
    	ST.elem[0].key=key;	
    	for(i=ST.length;ST.elem[i].key!=key;--i);
    	return i+1;
    }
    
    int Search_Bin(SSTable ST,KeyType key)
    {
    	//在该有序表ST中折半查找关键字等于key的数据元素。若找到,则函数值为
    	//该元素在表中的位置,否则为 0 
    	int mid;
    	int low = 1; 
    	int high = ST.length;
    	while(low<=high)
    	{
    		mid = (low + high)/2;
    		if(key!=ST.elem[mid].key)
    		return mid;
    	    else if(LT(key,ST.elem[mid].key))
    	        high = mid - 1 ;
    	    else low = mid + 1 ;
    	 } 
    	 return 0; 
    }//Search.Bin 
    int main()
    {
    	int i;
    	SSTable ST;
    	Init_Sq(ST);//构造一个空的顺序表 
    	
    	Create_Sq(ST,5);//创建一个非空顺序表 
    	
    	Output_Sq(ST);//输出顺序表 
    	
    	cout<<Search_Bin(ST,3);
    	cout<<Search_Sq(ST,3);
    }

    更多相关内容
  • 数据结构查找表

    万次阅读 2018-11-12 18:30:57
    今天学习数据结构看到了一个词-静态查找表,还有与之对应的动态查找表,然后我发现。 啊,这是个啥,好像知道又好像不知道,不就是查找吗,干嘛弄这些专业的说法,回头翻了一下数据结构的书,才发现......。 唉,...

    前言

    今天学习数据结构看到了一个词-静态查找表,还有与之对应的动态查找表,然后我发现。

    啊,这是个啥,好像知道又好像不知道,不就是查找吗,干嘛弄这些专业的说法,回头翻了一下数据结构的书,才发现......。

    唉,小小的抱怨一下,不过,我从这两个词联想到了一门基础但是要精通又不简单的学问,就是查找,然后还有前天被面试官问到的一个查找题,题目很简单,如何查找单向链表中倒数第K个数?当然你先遍历一遍数组,获取数组的总长度,然后再遍历一遍找倒数第K个数,当然可以,但是既然是面试题,这样的答案基本是凉凉的,我自己都不满意,更别提人家面试官了,当你抛出这个答案之后,面试官会说如果只遍历一遍呢?你就懵逼了,如果你和我一样懵逼的话,那么恭喜你,你现在还来得及,当然正确方法我就不说了,感兴趣的可以去想想,实在想不出来,我相信你会有办法的,xixixi,也不难。

    好了,说了这么多,今天既然发现了自己的一个薄弱区-查找,指不准以后哪天还会在查找这里栽倒,于是,何不在这之前好好梳理一下查找这块呢?

    目录

    1.静态查找表

    2.动态查找表

    3.哈希表

    正文

    首先我们需要明白下静态查找表和动态查找表的定义,所谓的静态查找表是指在查找过程中只进行查找操作,动态查找表就是在查找过程中还会进行插入和删除操作,例如,查找某个元素,若查找到了,则删除。

    1.静态查找表

    静态查找表可以有不同的表示方法,在不同的表示方法中,实现的查找操作方法也不同。

    这里列举平时遇到的最为常见的两种情况

    a.以顺序表或线性链表表示静态查找表,则查找可用顺序查找来实现

    b.以有序表(排好顺序的顺序表) 表示静态查找表,则查找可用折半查找(二分查找)来实现

    第一种,就是一个for循环的事,就不赘述了,这里看一下第二种情况,也就是二分查找的代码,思想就是从中间位置起开始查找,如果正好位于正中间,那么就找到了,如果比正中间数据大,那么在后半部分查找,假设整个数据是升序,如果比正中间数据小,那么在前半部分查找,依次类推,递归结束的标志就是左边界大于右边界,也就是已经不能再分了,如果此时还没查找到,那么就返回未查找到即可

    public class BinarySearch {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		int[] a=new int[]{2,3,5,8,9};
    		int index=search(a,50);
    		System.out.println(index);
    	}
    	public static int search(int[] a,int data){
    		return binarlSearch(a, 0, a.length-1,data);
    	}
    	public static int binarlSearch(int[] a,int left,int right,int data){
    		if(left>right)
    			return -1;
    		int mid=(left+right)/2;
    		if(a[mid]==data){
    			return mid;
    		}else if(a[mid]<data){
    			return binarlSearch(a, mid+1, right, data);
    		}else{
    			return binarlSearch(a, left, mid-1, data);
    		}
    	}
    }

    上面的只是查找里的入门知识,学任何东西都像打怪升级一样,先从小怪开始,由简变难,下面我们升级来打一个大点的怪!

    2.动态查找表

    动态查找表的特点是:表结构本身是在查找过程中动态生成的,即对于给定的key值,若表中存在其关键字等于key的记录,则查找成功返回,否则插入关键字等于key的记录。

    动态查找表也可有不同的表示方法,这里主要讨论以各种树结构表示时的实现方法。

    a.二叉排序树(又叫  二叉搜索树  二叉查找树)

    二叉排序树的特点是:

    1.若它的左子树不为空,则左子树上所有节点的值均小于它的根节点的值

    2.若它的右子树不为空,则右子树上所有节点的值均大于它的根节点的值

    3.它的左右子树也分别为二叉排序树

    在了解了这个树的性质之后,我们不难联想到二分查找的思想,只不过大同小异,首先和根节点比较,如果比根节点大,则在右子树中查找,如果比根节点小,则在左子树中查找,如果相等,那么正好查找到了,如果左子树也没有,右子树也没有,则查找失败。

    好了,我们掌握了上面的思想,不难写出下面的代码

    	public boolean contains(Node root, Node node) {
    		if (root == null) {
    			return false;
    		}
    		if (node.data == root.data) {
    			return true;
    		} else if (node.data > root.data) {
    			return contains(root.rChild, node);
    		} else {
    			return contains(root.lChild, node);
    		}
    	}

    代码不难理解,然后我们再考虑这样一种情况,就是一个有序的链表,是不是也符合二叉排序树的性质,也就是说我们查找的这棵二叉排序树是有可能退化为一个链表的,那么我们再对照着上面这个查找的代码去看,会发现查找的效率已经退化成了O(n),这显然不是我们想要看到的结果,我们想要的效果是尽可能的将一组数据分为等长的两部分,以达到类似“二分”的效果,只有这样最终的效率才可以达到O log(n)的最优效果,于是我们就引出了这样一个问题,如何保证二叉排序树查找的效率维持在O log(n)呢?接着往下看

    b.平衡二叉树

    在上面,我们发现如果不对二叉排序树做任何处理,发现查找的效率会有可能退化为链表的查找效率,所以我们期望有一种解决方案能避免效率的降低,现在再来想想,为什么我们的查找效率会降低,究其原因就是二叉树退化成了链表,那么我们必须以某种手段来防止退化,比如强制要求左右子树的高度差小于某个值等措施,于是我们自然而然想到了平衡二叉树。

     

    所以解决方案就是让二叉排序树转换为平衡二叉树,这个就好说了,主要涉及到四个操作,左左旋(LL)、右右旋(RR)、左右旋(LR)、右左旋(RL)。通过在插入一个元素的时候,判断是否符合平衡二叉树的性质,也就是左右子树的高度差是否小于1,如果不符合,那么根据情况做相应的旋转处理即可。

    由于几个旋转基本类似,只要掌握了一个,剩下的依葫芦画瓢即可,我们现在来看下左左旋的代码

    	// 左左翻转 LL
    	// 返回值为翻转后的根结点
    	private Node leftLeftRotation(Node node) {
    		// 首先获取待翻转节点的左子节点
    		Node lNode = node.lChild;
    
    		node.lChild = lNode.rChild;
    		lNode.rChild = node;
    
    		node.height = max(getHeight(node.lChild), getHeight(node.rChild)) + 1;
    		lNode.height = max(getHeight(lNode.lChild), node.height) + 1;
    
    		if (node == root) {
    			root = lNode;// 更新根结点
    		}
    		return lNode;
    	}

    剩下三个操作就不细说了,接下来我们再在插入和删除的时候,进行适当的判断,插入代码如下

    	public void insert(int data) {
    		if (root == null) {
    			root = new Node(data);
    
    		} else {
    			insert(root, new Node(data));
    		}
    	}
    
    	// node 为插入的树的根结点
    	// insertNode 为插入的节点
    	private Node insert(Node node, Node insertNode) {
    		if (node == null) {
    			node = insertNode;
    		} else {
    			if (insertNode.data < node.data) {// 将data插入到node的左子树
    				node.lChild = insert(node.lChild, insertNode);
    				// 如果插入后失衡
    				if (getHeight(node.lChild) - getHeight(node.rChild) == 2) {
    					if (insertNode.data < node.lChild.data) {// 如果插入的是在左子树的左子树上,即要进行LL翻转
    						node = leftLeftRotation(node);
    					} else {// 否则执行LR翻转
    						node = leftRightRotation(node);
    					}
    				}
    			} else if (insertNode.data > node.data) {
    				// 将data插入到node的右子树
    				node.rChild = insert(node.rChild, insertNode);
    				// 如果插入后失衡
    				if (getHeight(node.rChild) - getHeight(node.lChild) == 2) {
    					if (insertNode.data > node.rChild.data) {
    						node = rightRightRotation(node);
    					} else {
    						node = rightLeftRotation(node);
    					}
    				}
    			} else {
    				System.out.println("节点重复啦");
    			}
    			node.height = max(getHeight(node.lChild), getHeight(node.rChild)) + 1;
    		}
    		return node;
    	}

    删除代码如下

    	public void remove(int data) {
    		Node removeNode = new Node(data);
    		if (contains(root, removeNode)) {
    			remove(root, removeNode);
    		} else {
    			System.out.println("节点不存在,无法删除"+data);
    		}
    	}
    
    	// 删除节点
    	private Node remove(Node node, Node removeNode) {
    		if (node == null) {
    			return null;
    		}
    		// 待删除节点在node的左子树中
    		if (removeNode.data < node.data) {
    			node.lChild = remove(node.lChild, removeNode);
    			// 删除节点后,若失去平衡
    			if (getHeight(node.rChild) - getHeight(node.lChild) == 2) {
    				Node rNode = node.rChild;// 获取右节点
    				// 如果是左高右低
    				if (getHeight(rNode.lChild) > getHeight(rNode.rChild)) {
    					node = rightLeftRotation(node);
    				} else {
    					node = rightRightRotation(node);
    				}
    			}
    		} else if (removeNode.data > node.data) {// 待删除节点在node的右子树中
    			node.rChild = remove(node.rChild, removeNode);
    			// 删除节点后,若失去平衡
    			if (getHeight(node.lChild) - getHeight(node.rChild) == 2) {
    				Node lNode = node.lChild;// 获取左节点
    				// 如果是右高左低
    				if (getHeight(lNode.rChild) > getHeight(lNode.lChild)) {
    					node = leftRightRotation(node);
    				} else {
    					node = leftLeftRotation(node);
    				}
    			}
    		} else {// 待删除节点就是node
    				// 如果Node的左右子节点都非空
    			if (node.lChild != null && node.rChild != null) {
    				// 如果左高右低
    				if (getHeight(node.lChild) > getHeight(node.rChild)) {
    					// 用左子树中的最大值的节点代替node
    					Node maxNode = maxNode(node.lChild);
    					node.data = maxNode.data;
    					// 在左子树中删除最大的节点
    					node.lChild = remove(node.lChild, maxNode);
    				} else {// 二者等高或者右高左低
    					// 用右子树中的最小值的节点代替node
    					Node minNode = minNode(node.rChild);
    					node.data = minNode.data;
    					// 在右子树中删除最小的节点
    					node.rChild = remove(node.rChild, minNode);
    				}
    				
    			} else {
    				// 只要左或者右有一个为空或者两个都为空,直接将不为空的指向node
    				// 两个都为空的话,想当于最后node也指向了空,逻辑仍然正确
    				node = node.lChild == null ? node.rChild : node.lChild;// 赋予新的值
    			}
    		}
    		if(node!=null) {
    			node.height = max(getHeight(node.lChild), getHeight(node.rChild)) + 1;
    		}
    		return node;
    	}
    

     每次在插入和删除时进行这样的操作之后,我们的二叉排序树终于变成一颗平衡二叉树啦,这样我们再执行上面一模一样的查找代码时,查找的效率就可以稳定在O log(n),完美!

     

    其实仔细想想,这个问题,也是一个取舍的问题,虽然我们最后让二叉排序树的查找效率稳定为O log(n),但是我们却付出了不小的代价,就是每次插入以及删除的时候,都要进行大量的判断以及节点转换,这肯定会大大降低插入和删除的效率,与之带来的收益就是查找效率高,这样再一想,发现有点类似数组和链表的优缺点了,hhhh,事物总是有两面性,所以我们在实际使用时,也要根据场景来适当的做出取舍。

    3.哈希表

    在说哈希表之前,先回忆一下两个最简单的容器,一个是数组,一个是链表,这二者的优缺点我就不啰嗦了,之前的博客我也说过这样一个问题,既然数组查询快,链表插入删除快,就不能发明一种容器能兼具这二者的优点吗?这样岂不时省事多了,答案是能,没错,这个神奇的容器就是HashMap,而其核心就是哈希表,这时候,你兴冲冲的去查询哈希表,可能会遇到很多晦涩难懂的概念,什么关键字冲突,线性探测再散列,链地址法,再哈希等等,一下子头就大了,放心,我不会去给你灌输这些概念,我喜欢以实际使用的东西,或者叫“成品”来学习某个新的东西,然后再反过来看这些概念,这样就自然而然懂了,所以我们先简单了解HashMap的实现原理,再来看哈希表,就自然而然懂了。

    既然是了解HashMap的实现原理,最最正确的方式就是直接打开jdk的源码去看,重点看核心方法put和remove即可,限于篇幅,我就说下大致思想。

    我们首先需要知道的是HashMap存储的数据是键值对的形式,也就是key-value形式,然后就是HashMap里的一些重要成员变量及类,其中最重要的就是Node对象,每个Node对象含有key和value字段,用于保存插入的key和value值,Node数组的默认长度是16,当插入一个元素的时候,首先计算key的hash值,然后直接和数组长度-1做与运算,这样就定位到一个具体的下标,然后判断下标处是否有元素值存在,如果有,则以尾插法在该处形成一个链表,否则,就直接放入这个插入元素即可,所以最终效果就是这样的

    看了这个结构图后,我们再回到我们的主题--查找,我们再来看看HashMap是如何查找的,首先拿到key值,计算key的hash值,然后同样的方法,和长度减1做与运算,得到下标,如果该下标处为空,则返回找不到,如果不为空,则从链表头开始,逐个遍历该链表,直到找到对应的value值与给定value值相等,若链表遍历完了仍然没有找到,则返回找不到。

    我们现在再来看看这个设计有什么巧妙的地方,当我们在查询一个元素时,发现,对于哈希表来说,首先会根据key值来定位一个下标,这个巧妙利用了数组的优势,这样就不用去逐个遍历所有元素,然后如果发现该下标处已经存在了元素,则形成一个链表,而在形成一个链表之后,对同一个下标处的元素来说,插入删除的效率也变高了。或者换种通俗的话就是,使用数组将一个链表分割成了多个小段。总的来说这种设计就是结合了数组和链表,利用了二者的优势所在,完美结合!

    好了,到这里,其实就已经学习了哈希表的一种,如上图,就是链地址法解决冲突的哈希表,相信到这里你也明白了,所谓的链地址法的具体含义,就是形成一个链表来解决冲突问题。

    链地址法也是最常见的一种设计哈希表的方法,我们现在再来看看另外的两种。

    线性探测再散列法,这种设计方式设计的哈希表的原理就是,当插入一个元素的时候,同样的先定位到一个下标,然后如果该下标处已经存在了元素,则判断下标+1的地方是否有元素存在,同样的如果仍然有元素存在,则下标继续+1,直到对应下标处没有元素存在时,则将元素插在这个地方。

    再哈希法,这个设计方式就比较简单粗暴了,直接在计算key的hash值的方法时,也就是在定位具体的下标时,用两次hash函数来计算,这样原本一次hash计算到相同地方的元素,因为有第二次hash计算,所以会在二次hash函数处理之后,再次判断是否定位到了同一下标,若还是定位在统一下标,则继续hash函数处理,直到冲突不再发生。

    我们仍然回到我们的主旨--查找上来,对这两种方法设计的哈希表,我们在查找时就是先定位,然后如果不存在元素,则“查找返回空”,否则比对对应的value值,如果不相等,则根据设计方法(线性探测再散列或再哈希)得到“下一个地址”,然后判断“下一个地址”是否为要查找的元素。

    好了,到这里,基本说完了三种设计哈希表的方式以及对应的查找方法,个人觉得每一种方式都有自己的特点和适用场景,没有孰好孰坏,只有当我们都掌握了之后,我们才可以去选择用哪种方式来实现哈希表,完成业务要求。

    结语

    这次说的主要是查找,内容相对简单,但是查找这个东西,一但结合实际场景之后,还是有很多需要注意和深究的地方,比如海量数据排序和查找,所以只有会了基础,才能有选择的余地,以后实际场景中若是遇到了相关的问题,再总结归纳一篇“实际场景版”的,今天就到这里了。

     

    展开全文
  • 数据结构】之顺序表查找

    千次阅读 2020-09-28 18:06:48
    目录概念顺序表查找算法顺序表查找优化总结 概念 顺序查找又叫线性查找,是最基本的查找技术,他的查找过程是:从中第一个(或最后一个)记录开始,逐个进行记录的关键字和给定值比较,若记录的关键字和给定值相等...

    概念

    顺序查找又叫线性查找,是最基本的查找技术,他的查找过程是:从表中第一个(或最后一个)记录开始,逐个进行记录的关键字和给定值比较,若记录的关键字和给定值相等,则查找成功,找到所查的记录;如果直到最后一个(或第一个)记录,其关键字和给定值比较都不等时,则表中没有所查的记录,查找失败。

    顺序表查找算法

    //a为数组,n为要查找的数组个数,key为要查找的关键字
    int Sequential_Search(int *a,int n,int key)
    {
    	int i;
    	for(i=1;i<=n;i++)
    	{
    		if (a[i]==key)
    			return i;
    	}
    	return 0;
    }
    

    上面的代码非常简单,就是在数组a(注意元素值从下标1开始)中查找有没有关键字key,当你需要查找复杂表结构的记录时,只需要把数组a与关键字key定义成你需要的表架构和数据类型即可。

    顺序表查找优化

    其实上面的代码并非足够完美,因为每次循环时都需要对i是否越界,即是否小于等于n做判断。那么,我们可以设置一个哨兵,可以解决不需要每次让i与n作比较。

    /* 有哨兵顺序查找 */
    int Sequential_Search2(int *a,int n,int key)
    {
    	int i;
    	a[0]=key; //设置哨兵
    	i=n;  //循环从数组尾部开始
    	while(a[i]!=key)
    	{
    		i--;
    	}
    	return i;
    }
    

    上述代码是从尾部开始查找的,由于a[0]=key ,也就是说,如果在a[i]中有key,则返回i值,查找成功。否则一定在最终的a[0]处等于key,此时返回的是0,即说明a[1]~a[n]中没有关键字key,查找失败。
    这种在查找方向的尽头设置哨兵,免去了在查找过程中每一次比较后都要判断查找位置是否越界的小技巧,看似与原先的差别不大,但是如果总数据比较多时,效率提升很大。

    总结

    对于顺序表查找来说,查找成功最好的情况就是在第一个位置就找到了,算法时间复杂度为O(1),最坏的情况就是在最后一个位置才找到,需要n次比价,时间复杂度为O(n),当查找不成功时,需要n+1次比较,时间复杂度为O(n),平均查找次数为(n+1)/2,所以最终的时间复杂度还是O(n)。
    很明显,顺序查找技术是有很大缺点的,n很大时,查找的效率极其低下,不过优点也是有的,这个算法非常简单,对静态查找表的记录没有任何要求,在一些小型数据的查找时,是可以适用的。

    展开全文
  • 数据结构-链表篇

    千次阅读 2021-09-07 22:54:59
    数据结构-链表篇

    数据结构中数组和链表是是使用频率最高的基础数据结构。数组作为数据存储结构有一定的缺陷。在无序数组中,搜索性能差,在有序数组中,插入效率又很低,而且这两种数组的删除效率都很低,并且数组在创建后,其大小是固定了,设置的过大会造成内存的浪费,过小又不能满足数据量的存储。

    一、链表(Linked List)

    1.定义
      链表通常由一连串节点(“链结点”)组成,每个节点包含任意的实例数据(data fields)和一或两个用来指向上一个/或下一个节点的位置的链接(“links”)。
      链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。
    2.优缺点
      使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。
      链表是一种插入和删除都比较快的数据结构,缺点是查找比较慢。除非需要频繁的通过下标来随机访问数据,否则在很多使用数组的地方都可以用链表代替。
    3.图解
      在链表中,每个数据项都包含在“链结点”中,一个链结点是某个类的对象。每个链结点对象中都包含一个对下一个链接点的引用,链表本身的对象中有一个字段指向第一个链结点的引用,如下图所示:
    在这里插入图片描述

    二、单向链表(Single-Linked List)

    1.单向链表的具体实现
      单链表是链表中结构最简单的。一个单链表的节点(Node)分为两个部分,第一个部分(data)保存或者显示关于节点的信息,另一个部分(next)存储下一个节点的地址。最后一个节点存储地址的部分指向空值
      单向链表只可向一个方向遍历,一般查找一个节点的时候需要从第一个节点开始每次访问下一个节点,一直访问到需要的位置。而插入一个节点,对于单向链表,我们只提供在链表头插入,只需要将当前插入的节点设置为头节点,next指向原头节点即可。删除一个节点,我们将该节点的上一个节点的next指向该节点的下一个节点。
    2.图解
    在这里插入图片描述
      head为头节点,不存放任何的数据,只是充当一个指向链表中真正存放数据的第一个节点的作用。
    (1)节点添加
    (2)节点删除
    3.用单向链表实现栈

    三、双端链表

    1.双端链表的具体实现
      双端链表与单链表的区别在于它不只第一个链结点有引用,还对最后一个链结点有引用。
    在这里插入图片描述
      由于有着对最后一个链结点的直接引用,所以双端链表比传统链表在某些方面要方便。比如在尾部插入一个链结点。双端链表可以进行直接操作但传统链表只能通过next节点循环找到最后链结点操作,所以双端链表适合制造队列
      双端链表可以插入表尾,但是仍然不能方便的删除表尾,因为我们没有方法快捷地获取倒数第二个链结点,双端链表没有逆向的指针,这一点就要靠双向链表来解决了。
    2.用双端链表实现队列

    四、双向链表

    在这里插入图片描述
      双向链表即允许向前遍历,也允许向后遍历。实现这种特性的关键在于每个链结点既有下一个链结点的引用,也有上一个链结点的引用。

    五、有序链表

    存储有序数据的链表结构为有序链表(前面说到的所有链表都是无序的)。
      在有序链表中,数据是按照关键值有序排列的。一般在大多数需要使用有序数组的场合也可以使用有序链表。有序链表优于有序数组的地方是插入的速度(因为元素不需要移动),另外链表可以扩展到全部有效的使用内存,而数组只能局限于一个固定的大小中。
      在有序链表中插入和删除某一项最多需要O(N)次比较,平均需要O(N/2)次,因为必须沿着链表上一步一步走才能找到正确的插入位置;然而可以最快速度删除值,因为只需要删除表头即可,如果一个应用需要频繁的存取最小值,且不需要快速的插入,那么有序链表是一个比较好的选择方案。比如优先级队列可以使用有序链表来实现。

    六、跳表

    跳表(SkipList)是在有序链表的基础上发展起来的,跳表经常会B+等数据结构比较提及。
      增加了向前指针的链表叫作跳表。跳表全称叫做跳跃表,简称跳表。跳表是一个随机化的数据结构,实质就是一种可以进行二分查找的有序链表。跳表在原有的有序链表上面增加了多级索引,通过索引来实现快速查找。跳表不仅能提高搜索性能,同时也可以提高插入和删除操作的性能。

    具体可参考下面这篇文章中的举例:《跳表》

    抽象数据类型(ADT)

    总结

    本文中图片引用自:
    https://www.cnblogs.com/bjlhx/p/10751938.html

    展开全文
  • C语言数据结构顺序查找算法

    千次阅读 2019-06-04 11:58:46
    *顺序查找算法(重点是哨兵的设置) *创建一个数据结构体 *创建一个顺序的结构体 *顺序结构体里面包含 数据数组 和 数组长度 *采用两种查找方法 哨兵设置 普通查找 *哨兵排序算法的设置的好处是可以降低时间...
  • 数据结构实验报告五 查找

    千次阅读 2020-12-31 13:45:44
    数据结构实验报告:实验五 查找
  • 数据结构哈希表查找姓名

    千次阅读 2019-01-05 19:37:40
    数据结构哈希表查找姓名的课程设计 有没有大神能帮忙写一下这道题,课设的题目。用C语言 问题描述:针对某个集体中人名设计哈希,并完成相应的建表和查表程序。 要求: (1)假设人名为中国人姓名的汉语拼音形式。...
  • 数据结构查找

    千次阅读 多人点赞 2020-11-22 17:49:17
    查找表由同一类型的数据元素(或记录)构成 ​ 对查找表经常进行的操作 查找表是否存在某元素 从查找表中检索某特定元素的属性 在查找表中插入一个元素 在查找表中删除一个元素 静态查找表:只做查找表是否存在...
  • 【算法与数据结构 10】哈希——高效查找的利器

    千次阅读 多人点赞 2020-09-24 17:03:21
    大家都在看的高效《数据结构与算法》!
  • 数据结构–七大查找算法总结

    万次阅读 多人点赞 2018-08-06 17:13:43
    数据结构–七大查找算法总结 2017年08月15日 21:06:17 阅读数:10610 ...
  • 数据结构--静态查找表

    千次阅读 2019-07-10 11:14:49
    由于查找表中的数据元素之间不存在明显的组织规律,因此不便于查找。 为了提高查找的效率,需要在查找表中的元素之间人为地附加某种确定的关系,换句话说,用另外一种结构来表示查找表。 顺序查找表----顺序查找法 ...
  • 数据结构之顺序查找

    千次阅读 2019-08-09 21:38:22
    排序直接的数据结构介绍; 顺序查找和折半查找是顺序存储;二叉排序树是二叉树存储;哈希查抄是类图(和图的邻接存储相似); 头文件(Search.h); # ifndef _SORT_ typedef int KeyType; typedef ...
  • 顺序查找 //顺序查找 #include<stdio.h>...//顺序元素类型 int SeqSearch(SeqList R[],int n,int k) { int i=n; R[0].key=k;//R[0].key 为查找不成功的监视哨 while(R[i].key !=k)//由表尾向
  • 数据结构】顺序查找和折半查找

    千次阅读 多人点赞 2021-04-03 08:07:36
    摘要:在本篇文章中,主要讲述了在数据结构中所涉及的几大查找算法,包括:顺序查找、折半查找、分块查找和散列表查找。这些查找方式都是数据结构中最基本的查找方式,并且在数据结构中运用广泛。在查找算法中,最为...
  • ``` Status LocateElem(SqList L,ElemType e,Status(*compare)(ElemType,ElemType)) { ElemType *p; int i=1; p = L.elem ; while(i!compare(*p++,e)) ++i; if(i) return i; else return Error;...
  • 静态查找表——基于线性表的查找法 动态查找表——基于树表的查找法 哈希表——计算式查找法 基本概念 查找表 由同一类型的数据元素(记录)构成的集合。 查找的定义 给定一个值 key,在含有 n 个记录的表中找出...
  • 数据结构中的7种查找方法

    千次阅读 2020-06-14 17:16:16
    数据结构中的7种查找方法
  • C语言数据结构查找(顺序查找,折半查找

    千次阅读 多人点赞 2020-08-29 16:46:23
    C语言数据结构查找(顺序查找,折半查找) tips:前些天已经学习了树和图的相关知识,今天来总结下两种常用的查找方式(顺序查找,折半查找)。 为了演示方便,顺序查找和折半查找的数据存储结构就直接采用数组。...
  • 数据结构几种平均查找长度

    千次阅读 2020-04-16 17:39:35
    数据结构几种平均查找长度 总结的有关数据结构中平均查找长度ASL的三种计算小技巧: 1.顺序查找法的平均查找长度为:(n+1)/2 2.散列表的查找成功和查找不成功的平均查找长度 技巧(线性探测法和链地址法): ...
  • C语言数据结构顺序的顺序查找和折半查找的功能

    千次阅读 多人点赞 2020-05-31 20:07:54
    优点:对顺序数据元素的存储没有要求,顺序存储链式存储均可。 需注意:对于线性表的链式存储只能使用顺序查找. 折半查找,又称二分查找,它仅适用于有序的顺序 首先将给定值key与中间位置元素的关键字比较...
  • 数据结构-顺序基本操作的实现(含全部代码)

    万次阅读 多人点赞 2018-09-13 22:14:57
    今天起开始编写数据结构中的各种数据结构及其算法的实现。 主要依据严蔚敏版数据结构教材以及王道数据结构考研辅导书。 今天是线性表中的顺序的实现,主要实现函数如下,读者有需要可以评论,我可以适当加几个。...
  • 静态查找表* (本章存储结构只讲顺序存储,不讲链式存储) 1、顺序查找 优点:算法简单、适应面广,对表结构(顺序表or链表、有序or无序) 缺点:平均查找长度较大 O(n) 2、折半查找 优点:平均查找长度小、查找速度...
  • 查找:给定一个值,在查找表中确定一个其关键字与给定值得数据元素(或记录)。 查找包含有一下几种操做: 1、查询某个“特定”的数据元素是否在查找表当中; 2、检索某个“特定”的数据元素的相关属性; 3、在查找...
  • 编写函数FindList(L,x)查找顺序中的值为x的数据并返回索引,如果没找到则返回-1#include "stdafx.h" #include "SeqList.h" int main() { SeqList myList ; ListInitiate(&myList);//初始化顺序,长度为0 for ...
  • 一、线性结构查找 1、顺序查找 (1)无序的线性查找 基本思想:从线性表的一端开始,逐个检查关键字是否满足给定的条件。特点:当N比较大时,查找效率低。 (2)有序的线性查找:查效率比无序查找略高。 2、折半...
  • 顺序的实现之查找功能 实现文件 更新于2020年4月13日 **************************************************************/ #include <stdio.h> #include <stdlib.h> #include "SeqList.h" void SL_...
  • 数据结构和算法】动图演示,保姆级,二分查找算法,就怕你不会! ???? 作者:Linux猿 ???? 简介:CSDN博客专家????,华为云享专家????,C/C++、面试、刷题、算法尽管咨询我,关注我,有问题私聊! ???? 关注...
  • 数据结构-查找

    千次阅读 2018-04-26 14:52:00
    》基本概念 -查找表:用于查找的数据元素集合。查找表由同一类型的数据元素(或记录)构成。 -静态查找表: 在查找表中查看某个特定的数据元素是否在查找表中;检索某个特定元素的各种属性。 静态查找表在查找...
  • ASL吐血整理&&数据结构查找

    千次阅读 多人点赞 2020-06-21 18:24:20
    ASL(Average Search Length),即... 查找表:同一类数据元素(或记录)所构成的集合。 关键字:是数据元素(或记录)中某个数据项的值,用他可以标识一个数据元素(或记录),若此关键字可以唯一的标识一个,称 ...
  • 数据结构>折半查找算法实现

    千次阅读 2020-10-31 23:01:56
    提示:本篇主要是本小白大学期间对数据结构实验的一些基本代码功能实现,希望对一同数据结构的伙伴有所帮助。 提示:以下是本篇文章正文内容,下面案例可供参考 一、折半查找算法(采用顺序存储结构) 要求:编写...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,032,706
精华内容 413,082
关键字:

数据结构 查找表

数据结构 订阅