线性结构主要表示一个接一个的关系,或者没有什么关系,但是位置上如果表示一个接一个,那么也方便查询的集合关系。
主要有4种:
顺序存储结构
主要查询,少删除的话用顺序存储,因为是物理顺序。所以查询起来用下标,内存地址只需要做加法就可以。但是元素很多的话,需要重新申请内存。删除要移动很大块。
链表存储结构
删除,插入大部分的话,那么用链表,因为只需要修改几个节点就可以。添加也不需要重新申请内存。 但是查询就效率低,需要一个一个检索过去。因为位置不是放在一块。
栈
后进先出。
队列
先进先出。
环形缓冲区
顺序表
5个注意点: 1.java.Cannot create a generic array of T. java 不能建立泛型数组。一般采用这种方式 (T[]) new Object[mDEFAULTSIZE]; 2.高级语言,数组可以获得长度length,不需要自己额外多一个长度字段。 3.java 的数组,对于非基础类型来说,其实放置的是指针们。吃鲸。另外关于插入和删除数据,没有去找是否有整段移动内存的代码,一个一个效率还是慢了。 4.内部类是否用静态,原则上默认static.除非从关系上来说 和具体对象是一对一的,需要使用具体对象的数据和方法 5.迭代器的有个方法名hasnext? 分明代码是表达的是isValidate. java命名严谨性真是无语。 数组结构比较简单,没有必要复习。做一次就可以了。
arraylist 的内存结构是这样。
为什么会这样,是因为java库中数组的内存布局就已经成这样了
代码:
package com.linson.datastrcture; public interface IList<T> { public boolean add(T item); public boolean insert(int index,T item); public boolean remove(T item); public boolean clear(); public T get(int index); public int contain(T item);///-1 not exist. otherwize : index. public int size(); public boolean isEmpty(); }
package com.linson.datastrcture; import java.util.Iterator; //5个注意点: 1.java.Cannot create a generic array of T. java 不能建立泛型数组。一般采用这种方式 (T[]) new Object[mDEFAULTSIZE]; // 2.高级语言,数组可以获得长度length,不需要自己额外多一个长度字段。 // 3.java 的数组,对于非基础类型来说,其实放置的是指针们。吃鲸。另外关于插入和删除数据,没有去找是否有整段移动内存的代码,一个一个效率还是慢了。 // 4.内部类是否用静态,原则上默认static.除非从关系上来说 和具体对象是一对一的,需要使用具体对象的数据和方法 // 5.迭代器的有个方法名hasnext? 分明代码是表达的是isValidate. java命名严谨性真是无语。 //数组结构比较简单,没有必要复习。做一次就可以了。 public class MyArrayList<T> implements IList<T>,Iterable<T> { public MyArrayList() { //不可行,是因为T不能保证默认构造函数?但是也可以在内存中先存储一些指针地址啊。再之后分配好后,指针放回去不可以吗。没办法,反正java.Cannot create a generic array of T. //mData=new T[mDEFAULTSIZE]; //代替方案,创建对象的最底基类,object的数组。 Initialize(); } public boolean clear() { Initialize(); return true; } @SuppressWarnings("unchecked") private void Initialize() { mData=(T[]) new Object[mDEFAULTSIZE]; mUsed=0; } private int getCapcity() { return mData.length; } @SuppressWarnings("unchecked") public MyArrayList(int size) { mData=(T[]) new Object[size]; mUsed=0; } @SuppressWarnings("unchecked") private void bigger() { T[] tempArray=(T[]) new Object[getCapcity()*2]; for(int i=0;i<mData.length;i++) { tempArray[i]=mData[i]; } mData=tempArray; } public boolean add(T item) { return insert(mUsed, item); } public boolean insert(int index, T item) { if(mUsed>=getCapcity()) { bigger(); } if(index>=0 && index<=mUsed-1) { for(int i=mUsed-1;i>=index;i--) { mData[i+1]=mData[i]; } mData[index]=item; mUsed++; } else if(index==mUsed) { mData[index]=item; mUsed++; } else { throw new Error("index is outofbounds"); } return true; } public boolean remove(T item) { boolean ret=false; int index=contain(item); if(index!=-1) { for(int i=index+1;i<mUsed;i++) { mData[i-1]=mData[i]; } mData[mUsed-1]=null; mUsed--; ret=true; } return false; } public T get(int index) { if(index>=0 && index<=mUsed-1) { return mData[index]; } else { throw new Error("index is outofbounds"); } } public int contain(T item) { int ret=-1; for(int i=0;i<mUsed;i++) { if(item.equals(mData[i])) { ret=i; } } return ret; } public int size() { return mUsed; } public boolean isEmpty() { return mUsed==0; } public String getInfo() { return "size"+mUsed+". capicity:"+getCapcity(); } private T[] mData=null; private static final Integer mDEFAULTSIZE=8; private Integer mUsed=0; public Iterator<T> iterator() { return new MyArrayIterator(); } //用静态不方便,迭代器从关系上来说是对象级别,不是类级别,需要某个具体对象的数据和方法。 public class MyArrayIterator implements Iterator<T> { private int position=0; public boolean hasNext()//无力吐槽,这个方法是hasnext? 分明代码是表达的是isValidate. java这命名严谨性。 { return position<=mUsed-1; } public T next() { if(hasNext()) { return mData[position++]; } else { throw new Error("overofbound"); } } } }
测试代码:
//arraylist public static class Arraylist { public static void test() { //show info :capcity:xxx. size: //add->show info //list each element; //del.modify. //for each process a fun. MyArrayList<Integer> myData=new MyArrayList<Integer>(); for(int i=0;i<7;i++) { myData.add(i); } myData.insert(6, 11); myData.remove(6); LSLog.printLine(myData.getInfo(), 1); for(int i=0;i<myData.size();i++) { LSLog.printLine(myData.get(i).toString(), 1); } for (Integer myint : myData) { LSLog.printLine(myint.toString(), 1); } } }
注意点
1.头尾节点可以做成哨兵,一直存在,方便很多处理。很有意思的设计,可以在实际开发中多多使用这种技巧。 2.双链表对于大数据,插入还是有优化作用。 3.链表根据索引搜索不像顺序存储那样直接取下标是一个1的复杂度。而是n所以下先写个findnode的方法。来完成索引查找,以便给其他方法调用。 也是一个和顺序存储一样简单但想要完美必须花时间处理的例子,做一次就好。不值得复习重新
package com.linson.datastrcture; import java.util.Iterator; //1.头尾节点可以做成哨兵,一直存在,方便很多处理。很有意思的设计,可以在实际开发中多多使用这种技巧。 //2.双链表对于大数据,插入还是有优化作用。 //3.链表根据索引搜索不像顺序存储那样直接取下标是一个1的复杂度。而是n所以下先写个findnode的方法。来完成索引查找,以便给其他方法调用。 //也是一个和顺序存储一样简单但想要完美必须花时间处理的例子,做一次就好。不值得复习重新。 public class MyLinkedList<T> implements IList<T>,Iterable<T> { public MyLinkedList() { initionize(); } private void initionize() { mRoot=new MyLinkedNode<T>(null, null, null); mLast=new MyLinkedNode<T>(null, null, null); mRoot.mNext=mLast; mLast.mPre=mRoot; mSize=0; } //链表无法通过索引快速得到节点。所以先要完成这个功能。 public MyLinkedNode<T> getNode(int index) { MyLinkedNode<T> ret=null; if(index>=0 && index<=mSize-1) { MyLinkedNode<T> replacedNode=null; if(index>mSize/2) { replacedNode=mLast; for(int i=0;i<mSize-index;i++) { replacedNode=replacedNode.mPre; } } else { replacedNode=mRoot.mNext; for(int i=0;i<index;i++) { replacedNode=replacedNode.mNext; } } ret=replacedNode; } else { throw new Error("index is outofbound."); } return ret; } public boolean add(T item) { return insert(mSize, item); } public boolean insert(int index, T item) { boolean ret=false; MyLinkedNode<T> replaceNode=null; if(index>=0 && index<=mSize-1) { replaceNode=getNode(index); } else if(index==mSize) { replaceNode=mLast; } if(replaceNode!=null) { MyLinkedNode<T> tempNode=new MyLinkedNode<T>(item, replaceNode, replaceNode.mPre); tempNode.mPre.mNext=tempNode; tempNode.mNext.mPre=tempNode; mSize++; ret=true; } return ret; } public boolean remove(T item) { MyLinkedNode<T> theNode= getNodeByElement(item); if(theNode!=null) { theNode.mPre.mNext=theNode.mNext; theNode.mNext.mPre=theNode.mPre; mSize--; } else { throw new Error("can't find element"); } return true; } public boolean clear() { initionize(); return true; } public T get(int index) { MyLinkedNode<T> theNode= getNode(index); if(theNode!=null) { return theNode.mdata; } else { return null; } } // public int contain(T item) { throw new Error("please use getNodeByElement"); } public MyLinkedNode<T> getNodeByElement(T item) { MyLinkedNode<T> ret=null; MyLinkedNode<T> checknode=mRoot.mNext; for(int i=0;i<mSize;i++) { if(checknode.mdata.equals(item)) { ret=checknode; break; } checknode=checknode.mNext; } return ret; } public int size() { return mSize; } public boolean isEmpty() { return mSize==0; } private String Print() { return "size:"+mSize; } // private MyLinkedNode<T> mRoot=null;//小技巧头尾2个节点是哨兵节点,空数据也存在。2个节点的存在可以让真实头尾节点跟普通节点一样处理。 private MyLinkedNode<T> mLast=null; private Integer mSize=0;//冗余一个字段吧。应该是个常用的字段。 public Iterator<T> iterator() { return new MyLinkedListIterator(); } //node public static class MyLinkedNode<T> { public T mdata=null; public MyLinkedNode<T> mNext=null; public MyLinkedNode<T> mPre=null; public MyLinkedNode(T data,MyLinkedNode<T> next,MyLinkedNode<T> pre) { mdata=data; mNext=next; mPre=pre; } } public class MyLinkedListIterator implements Iterator<T> { private MyLinkedNode<T> mCurrent=(MyLinkedNode<T>) mRoot.mNext; public boolean hasNext() { return mCurrent!=mLast; } public T next() { T retT=mCurrent.mdata; mCurrent=mCurrent.mNext; return retT; } } }
public static class linkedList { public static void test() { MyLinkedList<Integer> myData=new MyLinkedList<Integer>(); myData.insert(0, 3); myData.add(4); myData.add(5); myData.insert(0, 2); //myData.remove(4); // for(int i=0;i<myData.size();i++) // { // LSLog.printLine(myData.get(i).toString(), 1); // } for(Integer data :myData) { LSLog.printLine(data.toString(), 1); } } }
栈 组合链表实现。
package com.linson.datastrcture; public class MyStack<T> { private MyLinkedList<T> myList2=new MyLinkedList<T>(); public T pop() { T result=top(); if(result!=null) { myList2.remove(myList2.mLast.mPre); } return result; } public T top() { T result=null; if(myList2.mLast.mPre!=myList2.mRoot) { result=myList2.mLast.mPre.mdata; } return result; } public Integer size() { return myList2.size(); } public boolean push(T item) { boolean result=false; return myList2.add(item); } }
队列 ,组合链表实现。
package com.linson.datastrcture; public class MyQuene<T> { private MyLinkedList<T> theLinkedList=new MyLinkedList<T>(); public T top() { T resulT=null; if(theLinkedList.size()>0) { resulT=theLinkedList.mRoot.mNext.mdata; } return resulT; } public T deQueue() { T resulT=top(); if(top()!=null) { theLinkedList.remove(theLinkedList.mRoot.mNext); } return resulT; } public void inQueue(T item) { theLinkedList.add(item); } public int size() { return theLinkedList.size(); } }