本篇文章给大家谈谈取线 *** 表的第i个元素的时间同i的大小有关,以及存取第i个元素及其前驱的值对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。
本文目录
一、线 *** 表的定义是什么它有什么特点它有什么作用
线 *** 表在VF中扮演着重要角色,它是任何涉及数据的知识的基础。线 *** 表是最基本、最简单、也是最常用的数据结构之一。它通过一对一的关系来连接数据元素,除了之一个和最后一个元素,其他元素都是首尾相接的。线 *** 表的逻辑结构简洁明了,易于实现和 *** 作。因此,在实际应用中,线 *** 表被广泛采用作为一种有效的数据结构。
线 *** 表的定义是一个包含至少一个元素(结点)的有限序列,这些元素除了之一个和最后一个外,都存在唯一的前驱和后继。线 *** 表可以表示为一个线 *** 序列:k1,k2,…,kn,其中k1是开始结点,kn是终端结点。线 *** 表是一种有序(次序)集,具有以下基本特征:
1. *** 中存在唯一的之一个元素。
2. *** 中存在唯一的最后一个元素。
3.除了最后一个元素,每个元素都有唯一后继。
4.除了之一个元素,每个元素都有唯一前驱。
2)Length(L):求表长度;求表中元素个数。
3)Get(L,i):取表中第i个元素(1≤i≤n)。
4)Prior(L,i):取i的前趋元素。
5)Next(L,i):取i的后继元素。
6)Locate(L,x):返回指定元素在表中的位置。
7)Insert(L,i,x): *** 元素。
9)Empty(L):判别表是否为空。
1.均匀 *** :对于同一线 *** 表的各数据元素,它们的数组长度是相同的。
2.有序 *** :各数据元素在线 *** 表中的位置取决于它们的顺序,存在唯一的“之一个“和“最后一个“数据元素,除了之一个和最后一个外,其他元素前面只有一个数据元素直接前趋,后面只有一个数据元素(直接后继)。
在线 *** 表的数据元素存储方面,常用的有顺序存储结构和链式存储结构两种。本章主要介绍使用数组实现线 *** 表数据元素的顺序存储及其应用。栈、队列和字符串都是线 *** 表的特殊情况,也称为受限的线 *** 结构。
二、j *** a中 List 与Set 的区别
*** 的,但是比较详细,楼主看看吧:
ArrayList Vector LinkedList区别与用法
ArrayList和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和 *** 元素,都允许直接序号索引元素,但是 *** 数据要设计到数组元素移动等内存 *** 作,所以索引数据快 *** 数据慢,Vector由于使用了synchronized *** (线程安全)所以 *** 能上比ArrayList要差,LinkedList使用双向链表实现存储,按序号索引数据需要进行向前或向后遍历,但是 *** 数据时只需要记录本项的前后项即可,所以 *** 数度较快!
线 *** 表,链表,哈希表是常用的数据结构,在进行J *** a开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构。这些类均在j *** a.util包中。本文试图通过简单的描述,向读者阐述各个类的作用以及如何正确使用这些类。
Collection是最基本的 *** 接口,一个Collection *** 一组Object,即Collection的元素(Elements)。一些Collection允许相同的元素而另一些不行。一些能排序而另一些不行。J *** a SDK不提供直接继承自Collection的类,J *** a SDK提供的类都是继承自Collection的“子接口”如List和Set。
所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection,有一个Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户 *** 一个Collection。
如何遍历Collection中的每一个元素?不论Collection的实际类型如何,它都支持一个iterator()的 *** ,该 *** 返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个元素。典型的用法如下:
Iterator it= collection.iterator();//获得一个迭代子
Object obj= it.next();//得到下一个元素
由Collection接口派生的两个接口是List和Set。
List是有序的Collection,使用此接口能够精确的控制每个元素 *** 的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于J *** a的数组。
和下面要提到的Set不同,List允许有相同的元素。
除了具有Collection接口必备的iterator() *** 外,List还提供一个listIterator() *** ,返回一个ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的 *** ,允许添加,删除,设定元素,还能向前或向后遍历。
实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。
LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert *** 在LinkedList的首部或尾部。这些 *** 作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。
注意LinkedList没有同步 *** 。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决 *** 是在创建List时构造一个同步的List:
List list= Collections.synchronizedList(new LinkedList(...));
ArrayList实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步。
size,isEmpty,get,set *** 运行时间为常数。但是add *** 开销为分摊的常数,添加n个元素需要O(n)的时间。其他的 *** 运行时间为线 *** 。
每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要 *** 大量元素时,在 *** 前可以调用ens *** eCapacity *** 来增加ArrayList的容量以提高 *** 效率。
和LinkedList一样,ArrayList也是非同步的(unsynchronized)。
Vector非常类似ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的 *** 时将抛出Conc *** rentModificationException,因此必须捕获该异常。
Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的 *** 使得Vector得以被当作堆栈使用。基本的push和pop *** ,还有peek *** 得到栈顶的元素,empty *** 测试堆栈是否为空,search *** 检测一个元素在堆栈中的位置。Stack刚创建后是空栈。
Set是一种不包含重复的元素的Collection,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。
很明显,Set的构造函数有一个约束条件,传入的Collection参数不能包含重复的元素。
请注意:必须小心 *** 作可变对象(Mutable Object)。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。
请注意,Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个value。Map接口提供3种 *** 的视图,Map的内容可以被当作一组key *** ,一组value *** ,或者一组key-value映射。
Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。
添加数据使用put(key, value),取出数据使用get(key),这两个基本 *** 作的时间开销为常数。
Hashtable通过initial capacity和load factor两个参数调整 *** 能。通常缺省的load factor 0.75较好地实现了时间和空间的均衡。增大load factor可以节省空间但相应的查找时间将增大,这会影响像get和put这样的 *** 作。
使用Hashtable的简单示例如下,将1,2,3放到Hashtable中,他们的key分别是”one”,”two”,”three”:
Hashtable numbers= new Hashtable();
numbers.put(“one”, new Integer(1));
numbers.put(“two”, new Integer(2));
numbers.put(“three”, new Integer(3));
要取出一个数,比如2,用相应的key:
Integer n=(Integer)numbers.get(“two”);
System.out.println(“two=”+ n);
由于作为key的对象将通过计算其散列函数来确定与之对应的value的位置,因此任何作为key的对象都必须实现hashCode和equals *** 。hashCode和equals *** 继承自根类Object,如果你用自定义的类当作key的话,要相当小心,按照散列函数的定义,如果两个对象相同,即obj1.equals(obj2)=true,则它们的hashCode必须相同,但如果两个对象不同,则它们的hashCode不一定不同,如果两个不同对象的hashCode相同,这种现象称为冲突,冲突会导致 *** 作哈希表的时间开销增大,所以尽量定义好的hashCode() *** ,能加快哈希表的 *** 作。
如果相同的对象有不同的hashCode,对哈希表的 *** 作会出现意想不到的结果(期待的get *** 返回null),要避免这种问题,只需要牢记一条:要同时复写equals *** 和hashCode *** ,而不要只写其中一个。
HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即null value和null key。,但是将HashMap视为Collection时(values() *** 可返回Collection),其迭代子 *** 作时间开销和HashMap的容量成比例。因此,如果迭代 *** 作的 *** 能相当重要的话,不要将HashMap的初始化容量设得过高,或者load factor过低。
WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收。
如果涉及到堆栈,队列等 *** 作,应该考虑用List,对于需要快速 *** ,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。
如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时 *** 作一个类,应该使用同步的类。
要特别注意对哈希表的 *** 作,作为key的对象要正确复写equals和hashCode *** 。
尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程。
Vector是同步的。这个类中的一些 *** 保证了Vector中的对象是线程安全的。而ArrayList则是异步的,因此ArrayList中的对象并不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的 *** 那么使用ArrayList是一个很好的选择,这样可以避免由于同步带来的不必要的 *** 能开销。
从内部实现机制来讲ArrayList和Vector都是使用数组(Array)来控制 *** 中的对象。当你向这两种类型中增加元素的时候,如果元素的数目超出了内部数组目前的长度它们都需要扩展内部数组的长度,Vector缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的50%,所以最后你获得的这个 *** 所占的空间总是比你实际需要的要大。所以如果你要在 *** 中保存大量的数据那么使用Vector有一些优势,因为你可以通过设置 *** 的初始化大小来避免不必要的资源开销。
在ArrayList和Vector中,从一个指定的位置(通过索引)查找数据或是在 *** 的末尾增加、移除一个元素所花费的时间是一样的,这个时间我们用O(1)表示。但是,如果在 *** 的其他位置增加或移除元素那么花费的时间会呈线形增长:O(n-i),其中n *** *** 中元素的个数,i *** 元素增加或移除元素的索引位置。为什么会这样呢?以为在进行上述 *** 作的时候 *** 中第i和第i个元素之后的所有元素都要执行位移的 *** 作。这一切意味着什么呢?
这意味着,你只是查找特 *** 置的元素或只在 *** 的末端增加、移除元素,那么使用Vector或ArrayList都可以。如果是其他 *** 作,你更好选择其他的 *** *** 作类。比如,LinkList *** 类在增加或移除 *** 中任何位置的元素所花费的时间都是一样的?O(1),但它在索引一个元素的使用缺比较慢-O(i),其中i是索引的位置.使用ArrayList也很容易,因为你可以简单的使用索引来代替创建iterator对象的 *** 作。LinkList也会为每个 *** 的元素创建对象,所有你要明白它也会带来额外的开销。
最后,在《Practical J *** a》一书中Peter Haggar建议使用一个简单的数组(Array)来代替Vector或ArrayList。尤其是对于执行效率要求高的程序更应如此。因为使用数组(Array)避免了同步、额外的 *** 调用和不必要的重新分配空间的 *** 作。
三、线 *** 表两种 存储结构各自的优缺点有哪些
1、 *** 和删除不需要移动 *** 时只需要对 *** 位置后的一个元素进行 *** 作,不需要大量的移动元素。空间有效利用高。
2、大量访问 *** 作时不如顺序存储结构,因为每次都需要从头开始遍历整个线 *** 表直到找到相应的元素为止。
3、可随机存取表中任一元素。因为有下标可以 *** 作可以快速的 *** 到指 *** 置的元素,但是不知道位置的话也需要顺序遍历。
4、 *** 或删除 *** 作时,需大量移动元素。合适在很少进行 *** 和删除运算的情况下。
5、 *** 中必存在唯一的一个“之一元素”。
6、 *** 中必存在唯一的一个“最后元素”。
7、除最后一个元素之外,均有唯一的后继(后件)。
8、除之一个元素之外,均有唯一的前驱(前件)。
9、MakeEmpty(L)这是一个将L变为空表的 *** 。
10、Length(L)返回表L的长度,即表中元素个数。
11、Get(L,i)这是一个函数,函数值为L中位置i处的元素(1≤i≤n)。
12、Locate(L,x)这是一个函数,函数值为元素x在L中的位置。
13、Insert(L,i,x)在表L的位置i处 *** 元素x,将原占据位置i的元素及后面的元素都向后推一个位置。
14、Delete(L,p)从表L中删除位置p处的元素。
15、IsEmpty(L)如果表L为空表(长度为0)则返回true,否则返回false。
16、Init(L)同之一个,初始化线 *** 表为空。
17、Tr *** erse(L)遍历输出所有元素。
18、Sort(L)对所有元素重新按给定的条件排序。
19、strstr(string1,string2)用于字符数组的求string1 *** 现string2的首 *** 。
取线 *** 表的第i个元素的时间同i的大小有关的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于存取第i个元素及其前驱的值、取线 *** 表的第i个元素的时间同i的大小有关的信息别忘了在本站进行查找哦。