数据结构--线性表

C++中有析构函数,用于销毁对象时释放内存,而Java中因为有gc(垃圾回收机制)所以就没有析构函数,但是java有finalize() 方法,两者的用途相近。

具体请参考链接:http://blog.csdn.net/jemasw/article/details/8470480

什么是线性表?

官方定义:线性表是n个数据元素的有限序列

顺序表和链表互为补充;

定义解读:n个(个数),元素(可以是复杂元素对象,也可以是单个数据),有限(有限的),序列(是一个序列集合)

线性表分为两大类:数组和链表

顺序表

前驱:指定元素前一个元素

后继:指定元素的后一个元素

优点:可以通过下标遍历寻址,所以遍历和寻址极为快速。

缺点:插入和删除元素,因为要移动后面的所有元素,所以较为缓慢。

链表

单链表:

单链表,每个节点分为两部分,分别为 数据域  指针域

initChainList(); 初始化链表

void destroyList(); 销毁链表,废弃

boolean isListEmpty(); 判断链表是否为空

int listLength(); 获取链表的长度

void clearList(); 清空链表的所有元素

Node listInsertHead(Node node); 插入头节点

Node listInsertTail(Node node); 插入尾节点

Node insertElement(int i, Node node); 指定位置插入节点

Node deleteElement(int i); 删除指定节点

Node getElement(int i); 获取指定位置节点

int elementLocate(Node node); 获取指定节点所在的位置

Node priorElement(Node node); 找到指定节点的前驱

Node nextElement(Node node); 找到指定节点的后继

void listTraverse(); 遍历链表

循环链表

简单的说,就是首尾相连的单链表即尾节点的指针域指向首节点的位置

双向链表

双向链表,每个节点分为三部分,分别为:

前指针域:顺向指向下一个节点的位置

数据域:数据节点

后指针域:逆向指向下一个节点的位置

静态链表

此处附上顺序表的创建代码:

package util;

public class MyList {
    //线性表本身
    private Object myList[];
    //线性表的大小,即最大容量
    private int listSize;
    //线性表的长度,即线性表中的元素个数
    private int myLength;
    
    
    
    public MyList() {
        super();
    }

    /**
     * 初始化线性表 - 顺序表
     * @param size
     */
    public MyList(int size) {
        listSize = size;
        //申请线性表内存
        myList = new Object[listSize];
        myLength = 0;
    }
    
    /**
     * 销毁线性表
     */
    public void DestroyList(){
        myList = null;
    }
    
    /**
     * 清空线性表元素
     */
    public void clearList(){
        myLength = 0;
    }
    
    /**
     * 判断线性表是否为空
     * @return
     */
    public boolean isListEmpty(){
        return myLength == 0 ? true : false;
    }
    
    /**
     * 获取线性表的元素个数
     * @return
     */
    public int listLength(){
        return myLength;
    }
    /**
     * 获取下标位置的元素
     */
    public Object getElement(int i)
    {
        //需要将i入参进行一定的限制,因为元素存在的位置坐标仅限于0到线性表的个数减一(即0~myLength-1),所以如果i小于0或者i大于等于线性表的长度都判定为获取失败返回null
        if(i < 0 || i >= myLength){
            return null;
        }
        return myList[i];
    }
    
    /**
     * 获取线性表中元素所在的位置(只获取第一个遇到的位置)
     * @param element
     * @return
     */
    public int elementLocate(Object element){
        for (int i = 0; i <= myLength; i++){
            if (element.equals(myList[i]))
            {
                return i;
            }
        }
        return -1;
    }
    
    /**
     * 获取指定元素前驱
     * @param element
     * @return
     */
    public Object priorElement(Object element){
        int i = elementLocate(element);
        if(i == -1){
            //如果i==-1那么则表示当前线性表中没有找到元素,所以直接判定失败,返回null
            return null;
        }else if(i == 0){
            //如果i==0则该元素本身就是第一个元素,前面不可能再有前驱,所以返回null
            return null;
        }else{
            return myList[i - 1];
        }
    }
    
    /**
     * 获取指定元素后缀
     * @param element
     * @return
     */
    public Object nextElement(Object element){
        int i = elementLocate(element);
        if(i == -1){
            return null;
        }else if(i == myLength-1){
            return null;
        }else{
            return myList[i + 1];
        }
    }
    
    /**
     * 在指定位置插入元素
     * @param i
     * @param element
     * @return
     */
    public Object insertElement(int i, Object element)
    {
        if(i < 0 || i > myLength)
        {
            return null;
        }
        
        //此处注意要从后向前依次将i后面的元素向后移位
        for (int j = myLength-1; j >= i; j--){
            //依次把前面的元素向后移位
            myList[j + 1] = myList[j];
        }
        
        myList[i] = element;
        
        myLength++;
        
        return element;
    }
    
    /**
     * 删除指定位置元素
     * @param i
     * @return
     */
    public Object deleteElement(int i){

        if (i < 0 || i >= myLength){
            return null;
        }
        
        Object element = myList[i];
        
        //此处注意要从前向后依次将i后面的元素向后移位,不用单独执行删除操作,因为在移位的过程中已经把i坐标的元素给覆盖了
        for (int j = i + 1; j < myLength; j++){
            //依次把后面的元素向前移位
            myList[j - 1] = myList[j];
        }
        
        myLength--;
        return element;
    }
    
    /**
     * 遍历线性表中的元素
     */
    public void listTraverse(){
        for (int i = 0; i <= myLength-1; i++){
            System.out.println(myList[i].toString());
        }
    }
}

  此处附上链表的结构代码:

package util;

import test.entity.Node;

public class MyChainList {
    
    private Node myChainList;
    
    private int listLength;
    
    /**
     * 初始化链表
     */
    public MyChainList() {
        //申请节点内存
        myChainList = new Node();
        
        myChainList.data = null;
        myChainList.next = null;
        
        listLength = 0;  
    }

    /**
     * 销毁链表,废弃
     */
    public void destroyList(){
        clearList();
        myChainList = null;
    }
    
    /**
     * 判断链表是否为空
     * @return
     */
    public boolean isListEmpty(){
        return 0 == listLength ? true :false;
    }
    
    /**
     * 获取链表的长度
     * @return
     */
    public int listLength(){
        return listLength;
    }
    
    /**
     * 清空链表的所有元素
     */
    public void clearList(){
        Node currentNode = myChainList;
        //初始节点的下一个节点,为第一个节点,找到第一个节点判断是否为空
        while(null != currentNode.next){
            Node temp = currentNode.next;
            //将当前节点删除
            currentNode = null;
            //查找下一个节点
            currentNode = temp;
        }
        currentNode.data = null;
        currentNode.next = null;
        listLength = 0;
    }
    
    /**
     * 插入头节点
     * @param node
     * @return
     */
    public Node listInsertHead(Node node){
        //将第一个元素指向的下一个节点,存放备用
        Node temp = myChainList.next;
        
        //从堆内存中申请空间,将数据放入内存
        Node newNode = new Node();
        if(null == newNode){
            return null;
        }
        newNode.data = node.data;
        
        //让新的节点指向,第一个节点原指向的节点
        newNode.next = temp;
        //将node节点放入第一个节点的后面
        myChainList.next = newNode;
        listLength ++;
        return newNode;
    }
    
    /**
     * 插入尾节点
     * @param node
     * @return
     */
    public Node listInsertTail(Node node){
        Node currentNode = myChainList;
        //重第一个节点开始循环查找下一个节点,知道找到尾节点
        while(null != currentNode.next)
        {
            currentNode = currentNode.next;
        }
      
        //从堆内存中申请空间,将数据放入内存
        Node newNode = new Node();
        if(null == newNode){
            return null;
        }
        newNode.data = node.data;
        newNode.next = null;
        
        //将新节点插入尾节点的后面
        currentNode.next = newNode;
        
        listLength ++;
        return newNode;
    }
    
    /**
     * 指定位置插入节点
     * @param i
     * @param node
     * @return
     */
    public Node insertElement(int i, Node node){
        
        //判断i是否合法
        if (i < 0 || i > listLength){
            return null;
        }
        
        //遍历节点找到 i 位置的上一个节点
        Node currentNode = myChainList;
        for (int j = 0; j < i; j++){
            currentNode = currentNode.next;
        }
        
        Node newNode = new Node();
        if (null == newNode){
            return null;
        }
        
        newNode.data = node.data;
        //将原位于i位置的节点放入新节点的后面
        newNode.next = currentNode.next;
        //将新节点,放入i上一个节点的后面
        currentNode.next = newNode;
        
        listLength ++;
        return newNode;
    }
    
    /**
     * 删除指定节点
     * @param i
     * @return
     */
    public Node deleteElement(int i){
        
        if (i < 0 || i >= listLength){
            return null;
        }
        
        //找到第i个节点,和i的上一个节点
        Node currentNode = myChainList;
        Node currentNodeBefore = null;
        for (int j = 0; j <= i; j++){
            currentNodeBefore = currentNode;
            currentNode = currentNode.next;
        }
        
        //将i位置后面的节点,放在i前面节点的后面
        currentNodeBefore.next = currentNode.next;
        Node temp = currentNode;
        
        currentNode = null;
        listLength --;
        return temp;
    }
    
    /**
     * 获取指定位置节点
     * @param i
     * @return
     */
    public Node getElement(int i){
        
        //过滤i的合理范围
        if (i < 0 || i >= listLength){
            return null;
        }
        
        // 找到第i个节点
        Node currentNode = myChainList;
        for (int j = 0; j <= i; j++){
            currentNode = currentNode.next;
        }
        
        return currentNode;
    }
    
    /**
     * 获取指定节点所在的位置
     * @param node
     * @return
     */
    public int elementLocate(Node node){
        
        //循环查找所有节点
        Node currentNode = myChainList;
        int count = 0;
        while(null != currentNode.next){
            currentNode = currentNode.next;
            //找到链表中第一个与指定节点匹配的节点
            if (currentNode.data.equals(node.data)){
                //返回当前循环的次数
                return count;
            }
            //每执行一次表示当前位置没有匹配的节点,注意不能放在if前面
            count++;
        }
        
        return -1;
    }
    
    /**
     * 找到指定节点的前驱
     * @param node
     * @return
     */
    public Node priorElement(Node node){
        
        //找到 指定节点 和 指定节点的 上一个节点
        Node currentNode = myChainList;
        Node currentNodeBefore = null;
        while(null != currentNode.next){
            currentNodeBefore = currentNode;
            currentNode = currentNode.next;
            
            //匹配到了第一个与指定节点相同的节点
            if (node.data.equals(currentNode.data)){
                //如果找到的对象是线性表中的第一个元素,那么他就没有前驱,返回null
                if (currentNodeBefore.equals(myChainList)){
                    return null;
                }
                return currentNodeBefore;
            }
        }
        return null;
    }
    
    /**
     * 找到指定节点的后继
     * @param node
     * @return
     */
    public Node nextElement(Node node){
        //遍历线性表,找到指定节点
        Node currentNode = myChainList;
        while(null != currentNode.next){
            currentNode = currentNode.next;
            //如果找到了元素
            if (currentNode.data.equals(node.data)){
                //判断该元素是否为线性表中的最后一个元素,最后一个元素没有后缀,直接返回null
                if (currentNode.next == null){
                    return null;
                }
                return currentNode.next;
            }
        }
        return null;
    }
    
    /**
     * 遍历链表
     */
    public void listTraverse(){
        //遍历链表中的所有元素,依次打印出他们的 数据域
        Node currentNode = myChainList;
        while(null != currentNode.next){
            currentNode = currentNode.next;
            currentNode.printNode();
        }
    }
}

  

猜你喜欢

转载自www.cnblogs.com/fuhui-study-footprint/p/9087917.html