Foreword
-
By the previous data structures and algorithms leading I know what some of the data structure of the concept and importance , we summarize relevant content Linear table today. Of course, I use
自己的理解解
to others. -
In fact, to be honest, many people still can not distinguish
线性表,顺序表,和链表
between the differences and connections !- Linear table :
逻辑结构
is the relationship between the exposure of external data, do not care about the underlying how. - Sequence table lists :
物理结构
he structure is realized in the real physical address of a structure. For example, the order is to use the table数组
to achieve. The list with指针
the completion of major work. Different structures have different differences in different scenarios.
- Linear table :
-
For java is concerned, we all know
List
the interface type, this is the logical structure, because he is the package a series of methods and data in a linear relationship. And concrete realization of the content is actually associated with the physical structure. Such as content storage arrays use order table, and a get, set, add method should基于数组
be done, based on the list指针
of. When we consider the relationship between the data object to be considered指针
property. A pointer and value.
FIG below with reference to a linear relationship analysis table. Some may be less precise, but wherein the reference may, according to this example and also back to FIG.
- For one
线性表
it.不管
It's具体实现
how the way we should have函数名称
and实现效果
should be consistent. You can feel it in the design of some of the structures. List of suchArraylist
andLinkedList
. Map of HashMap and currentHashMap their api interfaces are the same, but the underlying design and implementation is certainly different. - Therefore, object-oriented programming thinking, we can write the linear form an interface, and the order table lists can be embodied in
继承
methods of the interface, to improve readability. - Another point is more important, remember linear table structures and algorithms to achieve when data are beginners
固定类型
(int), with the advancement of knowledge, we should be used泛型
to achieve more reasonable. As for the specific design of the interface as follows:
Package LinerList; public interface ListInterface <T> { void the Init ( int initsize); // initialization table int length (); Boolean isEmpty (); // is empty int ElemIndex (T T); // find the number T getElem ( int index) throws Exception; // get the data in accordance with index void the Add ( int index, T T) throws Exception; // inserted data according to index void Delete ( int index) throwsException; void the Add (T T) throws Exception; // tail insertion void SET ( int index, T T) throws Exception; String toString (); // switch to output String }
- Sequence table is based on an array implemented, some To based on characteristics of the array. For sequential table should have a basis for the property
数组data
and alength
. - There should be noted that the size of the array initialization, you can
固定大小
, but if not enough memory available for I will扩大二倍
. Of course, this is likely to cause great problems because of the use of space浪费
. - Some basic amount is not to say the method, the following concepts and methods that focused on a number of confusing beginners to achieve. Here the order of the table compared to a group of people sitting on the bench.
add(int index,T t)
- Wherein the index number for the inserted position, t is the insertion of data
- According to the picture you insert operation is well understood. When you insert a time index, all elements must be behind him after a shift. You can see a bloated sexual penetration when the entire operation. So this is the order of the table
性能表现最差
place, frequent insertions, deletions.
- Similarly, deleting is very resource-intensive. Principles and insert similar, but people go,
空一个小板凳
the people behind the need往前挪
.
- 其他操作就很简单了。比如如果按照编号获取数据
getElem(int index)
,你可以直接根据数据坐标返回。a[index],而其他操作,可以通过遍历直接操作数组
即可。
- 我想,链表应该是很多人感觉很绕的东西,这个很大原因可能因为
指针
。很多人说java
没指针,其实java他也有隐形指针。只不过不能直接用罢了。 - 指针建立的数据关系往往比数组这些要抽象的多。对于指针域,你把他当成一个对象就好了,不过这个对象指向的是
另一个同等级对象
。对于这个关系,你可以比作每个person类。每个person类都有老公(老婆)
,而这个老公老婆也是一个实际对象,可以理解这更像一种逻辑约定关系
,而不是硬生生的关系吧。 - 指针你可以考虑成
脑子记忆
。上面的顺序表我们说它有序因为每个小板凳(数组)有编号
,我们可以根据这个来确定位置。而对于链表来说,你可以看作成一个站在操场上的一队人。而他的操作也略有不同,下面针对一些比较特殊和重要的进行归纳。
对于线性表,我们只需要一个data数组和length就能表示基本信息。而对于链表,我们需要一个node(head头节点)
,和length
,当然,这个node也是一个结构体。
class node<T>{ T data;//节点的结果 node next;//下一个连接的节点 public node(){} public node(T data) { this.data=data; } public node(T data, node next) { this.data = data; this.next = next; } }
当然,这个节点有数据域
和指针域
。数据域就是存放真实的数据,而指针域就是存放下一个node的指针。所以相比顺序表,如果用满数组情况下,链表占用更多的资源,因为它要存放指针占用资源。
add(int index,T t)
其中index为插入的编号位置,t为插入的数据
加入插入一个节点node
,根据index找到插入的前一个节点叫pre
。那么操作流程为
node.next=pre.next
如下1的操作,将插入节点后面联系起来。此时node.next和pre.next一致。pre.next=node
因为我们要插入node,而node链可以替代pre自身的next。那么直接将pre指向node。那么就相当于原始链表插入了一个node。
很多人搞不清什么是带头节点
和不带头节点
。带头节点就是head节点不放数据,第0项从head后面那个开始数。而不带头节点的链表head放数据,head节点就是第0位
。
主要区别:
- 带头节点和不带头节点的主要区别就在插入删除首位,尤其是首位插入。带头节点找元素需要多遍历一次因为它的第一个head节点是头节点,不存数据(
可看作一列火车的火车头
)。而方便的就是带头节点在首位插入更简单。因为插入第0位
也是在head的后面
。 - 而不带头节点的链表就需要特殊考虑首位。因为插入第0位其实是插入head的前面。假设有head,插入node。具体操作为:
- node.next=head;(node指向head,node这条链成我们想要的链)
- head=node;(很多人想不明白,其实这个时候
node才是
插入后最长链的首位节点
,head在他的后面,而在链表中head通常表示首位节点
,所以head不表示第二个节点,直接"="node节点
。这样head和node都表示操作完成的链表。但是对外暴露的只有head。所以head只能指向第一个节点!)
- 而在插入尾部的时候,需要注意尾部的
next
为null
。不能和插入普通位置相比!
按照index移除:delete(int index)
- 找到该index的节点node。node.next=node.next.nex
按照尾部移除(拓展):deleteEnd()
- 这个方法我没有写,但是我给大家讲一下,按照尾部删除的思想就是:
- 声明一个node为head。
- 当
node.next!=null
时node=node.next
指向下一个 - 当
node.next==null
时候。说明这个节点时最后一个。你可以node=null
。这个这个node的前驱pre的next就是null。这个节点就被删除了。
头部删除(带头节点):
- 带头节点的删除和普通删除一直。直接
head.next(第1个元素)
=head.next.next(第二个元素)
- 这样head.next就直接指向第二个元素了。第一个就被删除了
头部删除(不带头节点)
- 我们知道不带头节点的
第一个
就是存货真价实的元素
的。不带头节点删除也很简单。直接将head移到第二位
就行了。即:head=head.next
- 对于其他操作,主要时结合查找。而单链表的查找时
从head开始
。然后另一个节点team=head
或head.next
。然后用这个节点不停的等于它指向的next去查找我们需要的内容即while(循环条件){team=team.next}类似。 - 不同教程和人写的线性表也不一致,这里只给出一个样例学习使用而并不是标准,希望大家审视。
- 在实现上用了带头节点的链表实现,因为比较方便管理,不需要很多
if else
.
package LinerList; public class seqlist<T> implements ListInterface<T> { private Object[] date;//数组存放数据 private int lenth; public seqlist() {//初始大小默认为10 Init(10); } public void Init(int initsize) {//初始化 this.date=new Object[initsize]; lenth=0; } public int length() { return this.lenth; } public boolean isEmpty() {//是否为空 if(this.lenth==0) return true; return false; } /* * * @param t * 返回相等结果,为-1为false */ public int ElemIndex(T t) { // TODO Auto-generated method stub for(int i=0;i<date.length;i++) { if(date[i].equals(t)) { return i; } } return -1; } /* *获得第几个元素 */ public T getElem(int index) throws Exception { // TODO Auto-generated method stub if(index<0||index>lenth-1) throw new Exception("数值越界"); return (T) date[index]; } public void add(T t) throws Exception {//尾部插入 add(lenth,t); } /* *根据编号插入 */ public void add(int index, T t) throws Exception { if(index<0||index>lenth) throw new Exception("数值越界"); if (lenth==date.length)//扩容 { Object newdate[]= new Object[lenth*2]; for(int i=0;i<lenth;i++) { newdate[i]=date[i]; } date=newdate; } for(int i=lenth-1;i>=index;i--)//后面元素后移动 { date[i+1]=date[i]; } date[index]=t;//插入元素 lenth++;//顺序表长度+1 } public void delete(int index) throws Exception { if(index<0||index>lenth-1) throw new Exception("数值越界"); for(int i=index;i<lenth;i++)//index之后元素前移动 { date[i]=date[i+1]; } lenth--;//长度-1 } @Override public void set(int index, T t) throws Exception { if(index<0||index>lenth-1) throw new Exception("数值越界"); date[index]=t; } public String toString() { String vaString=""; for(int i=0;i<lenth;i++) { vaString+=date[i].toString()+" "; } return vaString; } }
package LinerList; class node<T>{ T data;//节点的结果 node next;//下一个连接的节点 public node(){} public node(T data) { this.data=data; } public node(T data, node next) { this.data = data; this.next = next; } } public class Linkedlist<T> implements ListInterface<T>{ node head; private int length; public Linkedlist() { head=new node(); length=0; } public void Init(int initsize) { head.next=null; } public int length() { return this.length; } public boolean isEmpty() { if(length==0)return true; else return false; } /* * 获取元素编号 */ public int ElemIndex(T t) { node team=head.next; int index=0; while(team.next!=null) { if(team.data.equals(t)) { return index; } index++; team=team.next; } return -1;//如果找不到 } @Override public T getElem(int index) throws Exception { node team=head.next; if(index<0||index>length-1) { throw new Exception("数值越界"); } for(int i=0;i<index;i++) { team=team.next; } return (T) team.data; } public void add(T t) throws Exception { add(length,t); } //带头节点的插入,第一个和最后一个一样操作 public void add(int index, T value) throws Exception { if(index<0||index>length) { throw new Exception("数值越界"); } node<T> team=head;//team 找到当前位置node for(int i=0;i<index;i++) { team=team.next; } node<T>node =new node(value);//新建一个node node.next=team.next;//指向index前位置的下一个指针 team.next=node;//自己变成index位置 length++; } @Override public void delete(int index) throws Exception { if(index<0||index>length-1) { throw new Exception("数值越界"); } node<T> team=head;//team 找到当前位置node for(int i=0;i<index;i++)//标记team 前一个节点 { team=team.next; } //team.next节点就是我们要删除的节点 team.next=team.next.next; length--; } @Override public void set(int index, T t) throws Exception { // TODO Auto-generated method stub if(index<0||index>length-1) { throw new Exception("数值越界"); } node<T> team=head;//team 找到当前位置node for(int i=0;i<index;i++) { team=team.next; } team.data=t;//将数值赋值,其他不变 } public String toString() { String va=""; node team=head.next; while(team!=null) { va+=team.data+" "; team=team.next; } return va; } }
package LinerList; public class test { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub System.out.println("线性表测试:"); ListInterface<Integer>list=new seqlist<Integer>(); list.add(5); list.add(6); list.add(1,8); list.add(3,996); list.add(7); System.out.println(list.ElemIndex(8)); System.out.println(list.toString()); list.set(2, 222); System.out.println(list.toString()); list.delete(4); System.out.println(list.toString()); System.out.println(list.length()); System.out.println("链表测试:"); list=new Linkedlist<Integer>(); list.add(5); list.add(6); list.add(1,8); list.add(3,996); list.add(7); System.out.println(list.ElemIndex(8)); System.out.println(list.toString()); list.set(2, 222); System.out.println(list.toString()); list.delete(4); System.out.println(list.toString()); System.out.println(list.length()); } }
输出:
线性表测试:
1
5 8 6 996 7
5 8 222 996 7
5 8 222 996
4
链表测试:
1
5 8 6 996 7
5 222 6 996 7
5 222 6 996
4
- 这里的只是简单实现,实现基本方法。链表也只是单链表。完善程度还可以优化。如果有错误还请大佬指正。
- Singly linked list
查询速度较慢
, because he needs to traverse from scratch. If the tail of frequent operation, the list may be considered not only in the head polyadenylationtail
node. The sequence table query speed may be fast but very time-consuming insertion. According to the needs of the practical application of choice! - java in Arraylist and LinkedList is to represent the two ways, but using a doubly linked list LinkedList optimization, and jdk api lot of optimization. So it
不用造轮子
can be directly used, but still very学习价值
in. - If there do not understand or do not understand can contact exchanges and discussions. I open
自家公众号
the door随时欢迎受访!
below shipments will continue to share! , You can feel good point a praise. - Public concern number bigsai the reply data structure can be obtained data structures and algorithms of a well-prepared information ! Super-rich.