线性表——顺序表——时间复杂度计算

  数据结构的核心思想是通过数据结构的思维来优化代码的算法,以此来提升程序的执行性能,缩短程序执行的时间。下面我来举两个例子,以此来说明数据结构的时间复杂度计算问题。

  由于我这里操作的是线性表——顺序表,所以说先把线性表——顺序表的源代码贴出来

AbstractLineMethod.java

package com.mycompany;

import util.ObjectHolder;

/**
 * Created by HP on 2017/9/6.
 */
public interface AbstractLineMethod {
    /**
     * 初始化线性表
     * @param size
     */
    void initList(int size);

    /**
     * 销毁线性表
     */
    void destroyList();

    /**
     * 清空线性表
     */
    void clearList();

    /**
     * 线性表判空
     * @return
     */
    boolean listEmpty();

    /**
     * 获取线性表的长度
     * @return
     */
    int listLength();

    /**
     * 获取指定位置处的元素
     * @param i
     * @param ele
     * @return
     */
    public boolean getElem(int i, ObjectHolder ele);

    /**
     * 获取该元素在线性表中第一次出现的位置
     * @param ele
     * @return
     */
    public int locateElem(ObjectHolder ele);

    /**
     * 获取指定元素的前驱
     * @param currentElem
     * @param preElem
     * @return
     */
    public boolean priorElem(ObjectHolder currentElem,ObjectHolder preElem);

    /**
     * 获取指定元素的后继
     * @param currentElem
     * @param nextElem
     * @return
     */
    public boolean nextElem(ObjectHolder currentElem,ObjectHolder nextElem);

    /**
     * 在线性表的指定位置处插入元素
     * @param i
     * @param ele
     * @return
     */
    public boolean listInsert(int i,Object ele);

    /**
     * 删除线性表指定位置处的元素
     * @param i
     * @param ele
     * @return
     */
    public boolean listDelete(int i,ObjectHolder ele);

    /**
     * 循环遍历线性表
     */
    public void listTraverse();

}

LineMethod.java

package com.mycompany;

import util.ObjectHolder;

/**
 * Created by HP on 2017/9/6.
 */
public class LineMethod implements AbstractLineMethod{

    private int m_size = 0;
    private Object[] m_pList = null;
    private int m_iLength = 0;

    /**
     * 初始化线性表
     * @param size
     */
    public void initList(int size){
        this.m_size = size;
        this.m_pList = new Object[size];
        this.m_iLength = 0;
    }

    /**
     * 销毁线性表
     */
    public void destroyList(){
        this.m_pList = null;
        this.m_size = 0;
        this.m_iLength = 0;
    }

    /**
     * 将线性表指针归零
     */
    public void clearList(){
        this.m_iLength = 0;
    }

    /**
     * 判空操作
     * 如果线性表为空,则返回true否则返回false
     * @return
     */
    public boolean listEmpty(){
        if(this.m_iLength == 0){
            return true;
        }
        return false;
    }

    /**
     * 返回线性表的长度
     * @return
     */
    public int listLength(){
        return m_iLength;
    }

    /**
     * 获取指定位置处的元素
     * @param i
     * @param ele
     * @return
     */
    public boolean getElem(int i, ObjectHolder ele){
        if(i < 0 || i >= m_size){
            return false;
        }
        ele.object = this.m_pList[i];
        return true;
    }

    /**
     * 寻找第一个满足ele的数据元素的位序
     * @param ele
     * @return
     */
    public int locateElem(ObjectHolder ele){
        for(int i = 0;i < this.m_iLength; i++){
            if(this.m_pList[i] == ele.object){
                return i;
            }
        }
        return -1;
    }

    /**
     * 获取指定元素的前驱,如果存在,则返回true,不存在则返回false
     * @param currentElem
     * @param preElem
     * @return
     */
    public boolean priorElem(ObjectHolder currentElem,ObjectHolder preElem){
        //如果查找元素不位于线性表,则返回false
        int temp = locateElem(currentElem);
        if(temp == -1){
            return false;
        }
        //第一个元素没有前驱,所以说应该加以排除
        if(temp == 0){
            return false;
        }
        preElem.object = this.m_pList[temp - 1];
        return true;
    }

    /**
     * 获取指定元素的后继,如果存在则返回true,如果不存在则返回false
     * @param currentElem
     * @param nextElem
     * @return
     */
    public boolean nextElem(ObjectHolder currentElem,ObjectHolder nextElem){
        //如果所查找元素不是位于线性表中,则返回false
        int temp = locateElem(currentElem);
        if(temp == -1){
            return false;
        }
        //最后一个元素没有后继,应该加以排除
        if(temp == this.m_iLength -1){
            return false;
        }
        nextElem.object = this.m_pList[temp + 1];
        return true;
    }

    /**
     * 在指定位置处插入指定元素,如果插入成功则返回true,失败则返回false
     * @param i
     * @param ele
     * @return
     */
    public boolean listInsert(int i,Object ele){
        if(i < 0 || i > this.m_iLength){
            return false;
        }
        for (int k = this.m_iLength - 1;k >= i;k --){
            this.m_pList[k + 1] = this.m_pList[k];
        }
        this.m_pList[i] = ele;
        this.m_iLength ++;
        return true;
    }

    /**
     * 在线性表中删除指定的元素,如果删除成功,则返回true,如果删除失败则返回false
     * @param i
     * @param ele
     * @return
     */
    public boolean listDelete(int i,ObjectHolder ele){
        if(i < 0 || i >= this.m_iLength){
            return false;
        }
        ele.object = this.m_pList[i];
        for(int k = i +1;k < this.m_iLength;k ++){
            this.m_pList[k - 1] = this.m_pList[k];
        }
        this.m_iLength --;
        return true;
    }

    /**
     * 循环遍历线性表中的元素
     */
    public void listTraverse(){
        for(int i = 0;i < this.m_iLength;i ++){
            System.out.println(this.m_pList[i]);
        }
    }


}

ObjectHolder.java

package util;

/**
 * Created by HP on 2017/9/6.
 */
public class ObjectHolder {

    public Object object;

}

  下面是对于该线性表的时间复杂度的计算示例

  示例1:

  现有现有线性表LA,LB,LA中的数组为:3,5,7,2,9,8,LB中的数组为:4,,6,0,1现将LB中的数组合并到LA中,方法为:

TestUnion.java

package com.mycompany;

import org.apache.log4j.Logger;
import org.junit.Assert;
import org.junit.Test;
import util.ObjectHolder;

/**
 * 现有线性表LA,LB
 * LA中的数组为:3,5,7,2,9,8
 * LB中的数组为:4,,6,0,1
 * 现将LB中的数组合并到LA中
 * Created by HP on 2017/9/12.
 */
public class TestUnion {

    private static final Logger log = Logger.getLogger(TestUnion.class);

    /**
     * 创建线性表LA
     * @return
     */
    public AbstractLineMethod createListLA(){
        Object e1 = 3;
        Object e2 = 5;
        Object e3 = 7;
        Object e4 = 2;
        Object e5 = 9;
        Object e6 = 8;
        AbstractLineMethod abstractLineMethod = new LineMethod();
        abstractLineMethod.initList(10);
        abstractLineMethod.listInsert(0,e1);
        abstractLineMethod.listInsert(1,e2);
        abstractLineMethod.listInsert(2,e3);
        abstractLineMethod.listInsert(3,e4);
        abstractLineMethod.listInsert(4,e5);
        abstractLineMethod.listInsert(5,e6);
        return abstractLineMethod;
    }

    /**
     * 创建线性表LB
     * @return
     */
    public AbstractLineMethod createListLB(){
        Object e1 = 4;
        Object e2 = 6;
        Object e3 = 0;
        Object e4 = 1;
        AbstractLineMethod abstractLineMethod = new LineMethod();
        abstractLineMethod.initList(10);
        abstractLineMethod.listInsert(0,e1);
        abstractLineMethod.listInsert(1,e2);
        abstractLineMethod.listInsert(2,e3);
        abstractLineMethod.listInsert(3,e4);
        return abstractLineMethod;
    }

    /**
     * 合并线性表LA与LB
     */
    @Test
    public void testUnion(){
        //集合A
        AbstractLineMethod la = createListLA();
        //线性表LA的顺序:3,5,7,2,9,8
        //集合B
        AbstractLineMethod lb = createListLB();
        //线性表LB的顺序:4,6,0,1
        //集合A的长度
        int laLenth = la.listLength();
        //集合B的长度
        int lbLenth = lb.listLength();
        ObjectHolder ele = new ObjectHolder();
        for(int i = 0;i < lbLenth;i ++){
            lb.getElem(i,ele);
            if(la.locateElem(ele) == -1){
                la.listInsert(laLenth ++,ele.object);
            }
        }
        //循环遍历新数组
        la.listTraverse();
        //输出结果:3,5,7,2,9,8,4,6,0,1
        Assert.assertEquals(10,la.listLength());
        log.info("合并后的线性表数组长度为:" + la.listLength());
    }

}

  示例2:

  现有非降序线性表LA,LB,其中线性表LA中的数组为:3,5,8,11,线性表LB中的数组元素为:2,6,8,9,11,15,20,现将LA与LB中的元素按照非降序顺序插入到空线性表LC中,方法为:

TestMergeList.java

package com.mycompany;

import org.apache.log4j.Logger;
import org.junit.Assert;
import org.junit.Test;
import util.ObjectHolder;

/**
 * 现有非降序线性表LA,LB
 * 其中线性表LA中的数组为:3,5,8,11
 * 线性表LB中的数组元素为:2,6,8,9,11,15,20
 * 现将LA与LB中的元素按照非降序顺序插入到空线性表LC中,方法如下:
 * Created by HP on 2017/9/13.
 */
public class TestMergeList {

    private static final Logger log = Logger.getLogger(TestMergeList.class);

    /**
     * 创建线性表LA
     * @return
     */
    public AbstractLineMethod createListLA(){
        Object e1 = 3;
        Object e2 = 5;
        Object e3 = 8;
        Object e4 = 11;
        AbstractLineMethod abstractLineMethod = new LineMethod();
        abstractLineMethod.initList(10);
        abstractLineMethod.listInsert(0,e1);
        abstractLineMethod.listInsert(1,e2);
        abstractLineMethod.listInsert(2,e3);
        abstractLineMethod.listInsert(3,e4);
        return abstractLineMethod;
    }

    /**
     * 创建线性表LB
     * @return
     */
    public AbstractLineMethod createListLB(){
        Object e1 = 2;
        Object e2 = 6;
        Object e3 = 8;
        Object e4 = 9;
        Object e5 = 11;
        Object e6 = 15;
        Object e7 = 20;
        AbstractLineMethod abstractLineMethod = new LineMethod();
        abstractLineMethod.initList(10);
        abstractLineMethod.listInsert(0,e1);
        abstractLineMethod.listInsert(1,e2);
        abstractLineMethod.listInsert(2,e3);
        abstractLineMethod.listInsert(3,e4);
        abstractLineMethod.listInsert(4,e5);
        abstractLineMethod.listInsert(5,e6);
        abstractLineMethod.listInsert(6,e7);
        return abstractLineMethod;
    }

    /**
     * 创建空的线性表LC
     * @return
     */
    public AbstractLineMethod createListLC(){
        AbstractLineMethod abstractLineMethod = new LineMethod();
        abstractLineMethod.initList(20);
        return abstractLineMethod;
    }

    /**
     * 合并到LC
     */
    @Test
    public void mergeToLC(){
        //创建线性表LA
        AbstractLineMethod la = createListLA();
        //创建线性表LB
        AbstractLineMethod lb = createListLB();
        //创建空的线性表LC
        AbstractLineMethod lc = createListLC();
        //初始化下标i,j
        int i = 0,j = 0;
        //当两个下标长度均在有效范围内时
        while((i < la.listLength()) && (j < lb.listLength())){
            ObjectHolder laEle = new ObjectHolder();
            ObjectHolder lbEle = new ObjectHolder();
            //如果元素laEle与元素lbEle都获取成功时
            if(la.getElem(i,laEle) && lb.getElem(j,lbEle)){
                //如果laEle元素的哈希值小于等于lbEle元素的哈希值,则将laEle元素插入到lc线性表中
                if(laEle.object.hashCode() <= lbEle.object.hashCode()){
                    lc.listInsert(i + j,laEle.object);
                    //插入后,线性表la中的指针后移一位
                    i ++;
                } else { //否则的话,此时laEle中的元素大于lbEle中的元素,则将lbEle元素插入到lc线性表中
                    lc.listInsert(i + j,lbEle.object);
                    //插入后,线性表lb中的指针后移一位
                    j ++;
                }
            }
        }
        //当其中的一个线性表循环遍历结束,另一个还没结束时,此时应该做的就是将没有循环结束的线性表中剩余的元素依次全部插入到lc中
        //当线性表la剩余时
        while(i < la.listLength()){
            ObjectHolder ele = new ObjectHolder();
            //如果la中的元素获取正确时,执行if语句中的代码
            if(la.getElem(i,ele)){
                //将该获取的元素插入到lc中
                lc.listInsert(i + j,ele.object);
                //将la中的元素指针(下标)自增1
                i ++;
            }
        }

        //当线性表lb剩余时
        while(j < lb.listLength()){
            ObjectHolder ele = new ObjectHolder();
            //如果lb中的元素获取正确时,执行if语句中的代码
            if(lb.getElem(j,ele)){
                //将该获取的元素插入到lc中
                lc.listInsert(i + j,ele.object);
                //将lb中的元素指针(下标)自增1
                j ++;
            }
        }

        //循环结束之后,循环遍历lc中的元素
        lc.listTraverse();
        log.info("合并后的数组长度为:" + lc.listLength());
        Assert.assertEquals(11,lc.listLength());

    }

}

  通过上述2个示例我们不难看出:
  在示例1中,每次在LA中插入一个LB中的元素,该元素都要循环遍历LA中的每一个元素,然后将其插入其中,其插入的耗时为:O(listLength(LA)*listLength(LB))

  在示例2中,虽然整体的代码量比示例1中的代码量要长,但是LA中的元素已经找到,只要符合条件即可插入到LC中,而LB中的元素也是一样的,这样一来,插入到LC中的元素,LA只需要循环一次,LB也只需要循环一次,所以说整体的时间消耗为:
O(listLength(LA)+listLength(LB))

  通过上述分析,我们可以发现,虽然示例2中的情况更复杂,代码量也更多,但是实际上在代码执行耗时操作时,示例2中的方法性能要明显优于示例1中的方法。

  下面是该项目的完整下载地址:

  • linear-table

你可能感兴趣的:(数据结构)