数据结构之线性结构

线性结构主要表示一个接一个的关系,或者没有什么关系,但是位置上如果表示一个接一个,那么也方便查询的集合关系。

主要有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();
    }
    
}

 

posted @ 2018-12-30 02:05  琴鸟  阅读(614)  评论(0编辑  收藏  举报