数据结构---线性表

线性表

顺序表

接口

/**
 * 线性表抽象数据类型的Java接口描述
 */
public interface IList {
     // 将一个已经存在的线性表置成空表
     void clear();
     // 判断当前线性表中的数据元素个数是否为0,若为0则函数返回true,否则返回false
     boolean isEmpty();
     // 求线性表中的数据元素个数并由函数返回其值
     int length();
     // 读取到线性表中的第i个数据元素并由函数返回其值。其中i取值范围为:0≤i≤length()-1,如果i值不在此范围则抛出异常
     Object get(int i) throws Exception;
     //在线性表的第i个数据元素之前插入一个值为x的数据元素。其中i取值范围为:0≤i≤length()。如果i值不在此范围则抛出异常,当i=0时表示在表头插入一个数据元素x,当i=length()时表示在表尾插入一个数据元素x
     void insert(int i, Object x) throws Exception;
     // 将线性表中第i个数据元素删除。其中i取值范围为:0≤i≤length()- 1,如果i值不在此范围则抛出异常
     void remove(int i) throws Exception;
     // 返回线性表中首次出现指定元素的索引,如果列表不包含此元素,则返回 -1
     int indexOf(Object x);
     // 输出线性表中的数据元素
     void display();
}

实现类

/**
 * 顺序表接口的描述
 */
public class SqList implements IList {
    private Object[] listElem;//线性表存储空间
    private int curLen;//当前长度

    //顺序表的构造函数,构造一个存储空间容量为maxSize的线性表
    public SqList(int maxSize){
        curLen=0;//置顺序表的当前长度为0
        listElem=new Object[maxSize];//为顺序表分配maxSize个存储单元
    }

    //将一个已经存在的线性表置成空表
    @Override
    public void clear() {
        curLen=0;//置顺序表的当前长度为0
    }

    //判断当前线性表中数据元素个数是否为0,若为0则函数返回true,否则返回false
    @Override
    public boolean isEmpty() {
        return curLen==0;
    }

    //求线性表中的数据元素个数并由函数返回其值
    @Override
    public int length() {
        return curLen;
    }

    //读取到线性表中的第i个数据元素并由函数返回其值。其中i取值范围为:0≤i≤length()-1,如果i值不在此范围则抛出异常
    @Override
    public Object get(int i) throws Exception {
        if (i<0 || i>curLen-1)
            throw new Exception("第" + i + "个元素不存在");
        return listElem[i];
    }

    //在线性表的第i个数据元素之前插入一个值为x的数据元素。其中i取值范围为:0≤i≤length()。如果i值不在此范围则抛出异常,
    //当i=0时表示在表头插入一个数据元素x,当i=length()时表示在表尾插入一个数据元素x
    @Override
    public void insert(int i, Object x) throws Exception {
        if (curLen==listElem.length)  //判断顺序表是否已满
            throw new Exception("顺序表已满,无法插入");
        if (i<0 || i>curLen)
            throw new Exception("插入位置不合理");
        for (int j=curLen;j>i;j--)
            listElem[j]=listElem[j-1];//插入位置及之后的元素后移
        listElem[i] = x; //插入x
        curLen++;//表长度增1
    }

    //将线性表中第i个数据元素删除。其中i取值范围为:0≤i≤length()- 1,如果i值不在此范围则抛出异常
    @Override
    public void remove(int i) throws Exception {
        if (i<0 || i>curLen-1)
            throw new Exception("删除位置不合理");
        for (int j=i;j<curLen-1;j++)
            listElem[j]=listElem[j+1];//被删除元素之后的元素左移
        curLen--;//表长度减1
    }

    //返回线性表中首次出现指定元素的索引,如果列表不包含此元素,则返回-1
    @Override
    public int indexOf(Object x) {
        int j=0;//j为计数器
        //从顺序表中的首结点开始查找,直到listElem[j]指向元素x或到达顺序表的表尾
        while (j<curLen && !listElem[j].equals(x))
            j++;
        if (j<curLen)//判断j的位置是否位于表中
            return j;
        else
            return -1;//x元素不在顺序表中
    }

    //输出线性表中的数据元素
    @Override
    public void display() {
        for (int j=0;j<curLen;j++)
            System.out.print(listElem[j]+" ");
        System.out.println();
    }
}

测试类

public class SqListTest {
    public static void main(String[] args) throws Exception {
        SqList sqList = new SqList(10);
        //插入
        for (int i=0;i<7;i++){
            sqList.insert(i,i);
        }
        //展示
        sqList.display();
        System.out.println(sqList.length());
        //读取
        System.out.println(sqList.get(3));
        //判断是否为空
        System.out.println(sqList.isEmpty());
        //删除
        sqList.remove(2);
        sqList.display();
        //查找
        System.out.println(sqList.indexOf(3));
    }
}

基本上实现了线性表,但是,有一个问题就是数据只能是int,因此,在上面的基础上,我们再对数据类型进行泛型化

/**
 * 线性表,对数据类型泛型化
 */
public class SequenceList<T> {
    //默认长度
    private int DEFAULT_SIZE=2;
    //定义一个数组用于保存线性表的长度
    private Object[] elementData;
    //用于保存数组长度
    private int capacity;
    //保存顺序表中当前元素的个数
    private int size=0;

    /**
     * 构造一个默认长度的空线性表
     */
    public SequenceList(){
        capacity=DEFAULT_SIZE;
        elementData=new Object[capacity];
    }

    /**
     * 用一个初始化元素来创建线性表
     * @param element 初始化元素
     */
    public SequenceList(T element){
        this();//调用空的构造方法
        elementData[0]=element;
        size++;
        System.out.println(size);
    }

    /**
     * 用一个元素和指定长度来创建线性表
     * @param element 元素
     * @param initSize 指定长度
     */
    public SequenceList(T element,int initSize){
        capacity=1;
        if (capacity<initSize)
            capacity=initSize;
        elementData=new Object[capacity];
        elementData[0]=element;
        size++;
        //System.out.println(size);
    }

    /**
     * 向顺序表中插入元素
     * @param element 待插入的元素
     * @param index 待插入的位置
     */
    public void insert(T element,int index){
        if (index<0 || index>size)
            throw new IndexOutOfBoundsException("数组越界异常");
        ensureCapacity(size+1);
        //把index以后的元素都后移一位
        System.arraycopy(elementData,index,elementData,index+1,size-index);
        elementData[index]=element;
        size++;
        //System.out.println(size);
    }

    /**
     * 确保数组所需长度大于数组原有长度
     * @param mCapacity 数组所需长度
     */
    private void ensureCapacity(int mCapacity) {
        if (mCapacity>capacity){
            capacity=mCapacity+2;
            //System.out.println("capacity:"+capacity);
            elementData= Arrays.copyOf(elementData,capacity);
        }
    }

    /**
     * 表长
     * @return
     */
    public int length(){
        return size;
    }

    /**
     * 向表中添加元素
     * @param element
     */
    public void add(T element){
        insert(element,size);
    }

    /**
     * 得到线性表存储的对象
     * @param index
     * @return
     */
    public T get(int index){
        if (index<0 || index>size)
            throw new IndexOutOfBoundsException("数组越界异常");
        return (T)elementData[index];
    }

    /**
     * 判断线性表是否为空
     * @return
     */
    public boolean isEmpty(){
        return size==0;
    }

    /**
     * 清空线性表
     */
    public void clear(){
        Arrays.fill(elementData,null);
        size=0;
    }

    /**
     * 获取指定位置的前一个元素
     * @param index 线性表位置,若是取线性表最后一个元素,必须index = size
     * @return
     */
    public T priorElem(int index){
        if (index>0 && index<size+1)
            return (T)elementData[index-1];
        else
            throw new IndexOutOfBoundsException("数组越界异常");
    }

    /**
     * 删除指定位置的元素
     * @param index
     */
    public void delete(int index){
        if (index<0 || index>size-1)
            throw new IndexOutOfBoundsException("数组越界异常");
        else
            System.arraycopy(elementData,index+1,elementData, index, size-index-1);
        size--;
        //清空最后一个元素
        elementData[size]=null;
    }

    /**
     * 获取指定线性表位置的后一个元素
     * @param index 线性表位置,若是取线性表第0个元素,必须index=-1
     * @return
     */
    public T nextElem(int index){
        if (index==-1)
            return (T)elementData[0];
        else if (index<size-1&&index>-1)
            return (T)elementData[index+1];
        else
            throw new IndexOutOfBoundsException("数组越界异常");
    }

    /**
     * 输出数组中所有数据
     */
    public void display() {
        for (int j=0;j<size;j++)
            System.out.print(elementData[j]+" ");
        System.out.println();
    }
}

测试类

public class SequenceListTest {
    public static void main(String[] args) {
        SequenceList sequenceList = new SequenceList(5,6);
        for (int i=0;i<3;i++)
            sequenceList.insert(i+2,i);
        System.out.println(sequenceList.length());
        sequenceList.add(10);
        System.out.println(sequenceList.length());
        System.out.println(sequenceList.get(4));
        System.out.println(sequenceList.isEmpty());
        System.out.println(sequenceList.priorElem(4));
        sequenceList.display();
        sequenceList.delete(2);
        sequenceList.display();
        System.out.println(sequenceList.nextElem(2));
    }
}

链式表

单向链表

单向链表的简单操作

/**
 * 单向链表
 */
public class Node02 {
    String data;//值域
    Node02 nextNode;//指针域

    //通过构造方法创建节点
    public Node02(String data, Node02 nextNode) {
        this.data = data;
        this.nextNode = nextNode;
    }

    public Node02() {
    }

    public Node02(String data) {
        this.data = data;
    }

    //添加节点(尾部插入)
    public void add(Node02 node02) {
        if (this.nextNode == null)
            this.nextNode = node02;
        else
            //如果当前节点不为空时,就取出当前节点下一个节点,然后调用自己的方法
            this.nextNode.add(node02);
    }

    //显示节点
    public void show() {
        //通过当前这个节点,获取他的内容,然后判断他的下一个节点是否存在:递归调用
        System.out.print(this.data + "---");
        if (this.nextNode != null)
            this.nextNode.show();
    }

    //在链表中查询指定节点是否存在
    public boolean check(String data) {
        if (data.equals(this.data)) {
            return true;
        } else {
            if (this.nextNode != null)
                //如果传入过来的数据和链表中节点的值域不相等,向下一个节点走
                return this.nextNode.check(data);
            else
                return false;
        }
    }

    /**
     * 删除节点
     * @param node02 传递一个节点(就是你要删除的节点)
     * @param data 对比的参数
     */
    public void delete(Node02 node02,String data){
        if (this.data.equals(data)){
            node02.nextNode=this.nextNode;//自己的后继要作为自己的前驱的后继
        }else {
            if (this.nextNode!=null)
                this.nextNode.delete(this,data);
        }
    }


    //定义一个头节点
    Node02 root;//根节点
    //插入节点(如果没有头节点,他就作为头节点,如果有头节点,他就往后面加)
    public void firstAddNode(String data){
        Node02 newNode=new Node02(data);
        if (root==null){
            this.root=newNode;//这个新节点作为根节点
        }else {
            this.root.add(newNode);//调用前面的add()(尾插法)
        }
    }

    //显示上面的方法
    public void show02() {
        if (root!=null) { // 如果我们的根节点不为空的时候
            this.root.show(); //显示当前节点中的内容
        }
    }

    //查询节点
    public boolean checkNode(String data){
        return this.root.check(data);//从根节点开始找起
    }

    //删除链表中的数据
    public void deleteNode(String data){
        //通过传入的参数,调用方法checkNode,如果返回的是true,在当前这个链表中找到
        if (checkNode(data)){
            //传入的参数和根的数据一样,其实就是删除根
            if (this.root.equals(data))
                this.root=this.root.nextNode;//根的下一个节点做根
            else
                //删除的不是根节点的时候,调用前面的删除方法
                this.root.delete(root,data);
        }
    }
}

测试类

public class NodeTest02 {
    public static void main(String[] args) {
        Node02 node1 = new Node02("1号车厢", null);
        Node02 headNode = new Node02("火车头", node1);
        Node02 node2=new Node02("2号车厢",null);
        Node02 node3=new Node02("3号车厢",null);
        Node02 node4=new Node02("4号车厢",null);
        headNode.add(node2);
        headNode.add(node3);
        headNode.add(node4);

        headNode.show();
        System.out.println();
        System.out.println(headNode.check("2号车厢"));

        node3.delete(node2,"3号车厢");
        headNode.show();

        Node02 node02 = new Node02("火车司机", null);
        headNode.firstAddNode("火车司机");
        headNode.show02();

//        Node02 node021 = new Node02("", null);
//        node021.firstAddNode("超级火车头");
//        node021.show02();

        System.out.println();
        Node02 node021 = new Node02();
        node021.firstAddNode("火车头--->");
        node021.firstAddNode("1号--->");
        node021.firstAddNode("2号--->");
        node021.firstAddNode("3号--->");
        node021.firstAddNode("4号--->");
        node021.show02();
        System.out.println();
        System.out.println(node021.checkNode("1号--->"));

        node021.deleteNode("1号--->");
        node021.show02();
    }
}
/**
 * 单向链表的具体的操作
 */
public class SingleLinkedList {
    private int size;//链表的节点个数
    private SingleNode head;//头节点
    //构造方法进行初始化
    public SingleLinkedList(){
        this.size=0;
        this.head=null;
    }

    //判断当前链表是否为空链表
    public boolean isEmpty() {
        return size==0;
    }

    //头插法插入节点到链表中
    public String addHead(String obj){
        SingleNode singleNode=new SingleNode(obj);//生成一个新的节点
        if (size==0) {
            head = singleNode;//如果为空的时候,链表为空链表,当前这个节点做根节点
        }else{
            singleNode.setNextNode(head);//让头节点作为新节点的下一个节点
            head=singleNode;//新节点作为头节点来使用
        }
        size++;
        return obj;
    }

    //显示节点信息
    public void display(){
        if (size>0){
            SingleNode singleNode=head;//链表的大小不为0的时候,取到头节点
            int tempSize=size;//定义出来的一个中间变量
            //当前链表只有一个根节点
            if (tempSize==1){
                System.out.println("["+singleNode.getData()+"]");
            }

            while (tempSize>0){
                //前这个节点和头节点一样的,打印信息
                if (singleNode.equals(head))
                    System.out.print(singleNode.getData()+",");
                //判断下一个节点不存在,直接打印
                else if (singleNode.getNextNode()==null)
                    System.out.print(singleNode.getData());
                //下一个节点还存在,就直接打印
                else {
                    System.out.print(singleNode.getData()+",");
                }
                singleNode=singleNode.getNextNode();
                tempSize--;
            }
        }else
            System.out.println("链表中没有数据");
    }

    //删除头部元素
    public String delete(){
        String str=null;
        if (isEmpty())
            System.out.println("当前这个是一个空的链表,不需要删除!");
        else {
            str=(String) head.getData();
            head=head.getNextNode();
            size--;
        }
        return str;
    }

    //查找指定元素,找到了返回节点SingleNode,找不到返回null
    public SingleNode find(String str){
        SingleNode singleNode=head;//这个作为中间节点,把头节点给这个中间节点,查的时候从头节点开始
        int tempSize=size;
        while (tempSize>0){
            if (str.equals(singleNode.getData())){
                return singleNode;
            }else {
                singleNode=singleNode.getNextNode();
            }
            tempSize--;
        }
        return null;
    }

    //删除指定的元素,删除成功返回true
    public boolean delete(String value){
        if (size==0)
            return false;
        //做了两个节点,让他们初始的时候都指向头节点
        SingleNode current=head;
        SingleNode previous = head;
        while (!current.getData().equals(value)){
            if (current.getNextNode()==null)
                return false;
            else {
                previous=current;
                current=current.getNextNode();
            }
        }

        //如果删除的节点是第一个节点
        if (current==head){
            head=head.getNextNode();
            size--;
        }else {
            previous.setNextNode(current.getNextNode());
            size--;
        }
        return true;
    }
}
/**
 * 单向链表中的节点类
 */
public class SingleNode {
    private Object data;
    private SingleNode nextNode;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public SingleNode getNextNode() {
        return nextNode;
    }

    public void setNextNode(SingleNode nextNode) {
        this.nextNode = nextNode;
    }

    //只构造值域,指针域通过方法给定
    public SingleNode(Object data) {
        this.data = data;
    }
}
public class SingleNodeTest {
    public static void main(String[] args) {
        SingleLinkedList singleLinkedList = new SingleLinkedList();
        singleLinkedList.addHead("3号车厢");
        singleLinkedList.addHead("2号车厢");
        singleLinkedList.addHead("1号车厢");
        singleLinkedList.addHead("火车头");
        singleLinkedList.display();

        singleLinkedList.delete();
        System.out.println();
        singleLinkedList.display();

        System.out.println();
        System.out.println(singleLinkedList.find("1号车厢").getData());

        System.out.println(singleLinkedList.delete("2号车厢"));
        singleLinkedList.display();
    }
}

双向链表
/**
 * 双向链表
 */
public class DoublePointLink {
    private Node head;//头节点
    private Node tail;//尾节点
    private int size;//记录当前节点

    public DoublePointLink() {
        this.size=0;
        this.head=null;
        this.tail=null;
    }

    //在链表头部添加节点
    public void addHead(Object data){
        Node newNode = new Node(data);//插入头节点的新节点
        if (size==0){
            head=newNode;
            tail=newNode;
            size++;
        }else {
            head.setPrev(newNode);
            newNode.setNext(head);
            head=newNode;
            size++;
        }
    }

    //尾部插入数据
    public void addTail(Object data){
        Node newNode=new Node(data);
        if (size==0){
            head=newNode;
            tail=newNode;
            size++;
        }else {
            tail.setNext(newNode);
            newNode.setPrev(tail);
            tail=newNode;
            size++;
        }
    }

    //删除链表头
    public Node deleteHead(){
        Node node=head;
        if (size!=0){
            head=head.getNext();
            head.setPrev(null);
            size--;
        }
        return node;
    }

    //删除链表尾
    public Node deleteTail(){
        Node node=tail;
        if (size!=0){
            tail=tail.getPrev();
            tail.setNext(null);
            size--;
        }
        return node;
    }

    //显示节点信息
    public void display(){
        if (size>0){
            Node node=head;//把头部节点放在中间节点
            int tempSize=size;
            if (tempSize==1){
                System.out.println("当前链表只有1个节点:"+node.getData());
            }
            while (tempSize>0){
                if (node.equals(head))
                    System.out.print(node.getData()+"--->");
                else if (node.getNext()==null)
                    System.out.print(node.getData());
                else
                    System.out.print(node.getData()+"--->");
                node=node.getNext();
                tempSize--;
            }
            System.out.println();
        }else
            System.out.println("当前链表为空");
    }
}
/**
 * 链表的节点(值域和指针域)
 */
public class Node {
    private Object data;//值域
    private Node next;//指针域,指向后一个节点
    private Node prev;//指向前一个节点
    public Node(Object data) {
        this.data = data;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public Node getNext() {
        return next;
    }

    public void setNext(Node next) {
        this.next = next;
    }

    public Node getPrev() {
        return prev;
    }

    public void setPrev(Node prev) {
        this.prev = prev;
    }
}
public class Test {
    public static void main(String[] args) {
        DoublePointLink doublePointLink = new DoublePointLink();
        doublePointLink.addHead("火车头");
        doublePointLink.addHead("火车司机");
        doublePointLink.display();
        doublePointLink.addTail("第一节车厢");
        doublePointLink.addTail("第二节车厢");
        doublePointLink.addTail("第三节车厢");
        doublePointLink.addTail("第四节车厢");
        doublePointLink.display();
        doublePointLink.deleteHead();
        doublePointLink.display();
        doublePointLink.deleteTail();
        doublePointLink.deleteTail();
        doublePointLink.display();
    }
}

循环链表
/**
 * 循环链表
 * 约瑟夫问题(隔几个淘汰一个)
 * 例:罗马人攻占了乔塔帕特,41人藏在一个山洞中躲过了这场浩劫。
 * 这41个人中为了表示不向罗马人屈服,决定集体自杀。
 * 大家决定了一个自杀方案,所有这41人围成一个圆圈,由第一个人开始顺时针报数,
 * 每报数为3的人就立刻自杀,然后由下一个人重新开始报数任然是每报数为3的人就立刻自杀,......,
 * 直到所有人都自杀死亡为止.
 */
public class CircularLinkedList {
    //内部类 节点的值域与指针域
    class node{
        node next;
        int data;

        public node getNext() {
            return next;
        }

        public void setNext(node next) {
            this.next = next;
        }

        public int getData() {
            return data;
        }

        public void setData(int data) {
            this.data = data;
        }
    }

    /**
     * 创建循环链表的过程
     * @param totalCol 循环链表里的个数
     * @return
     */
    public node createNodes(int totalCol){
        node head=null;
        node[] nodes = new node[totalCol];//对象数组,存放每个的节点
        //往数组中放入节点
        for (int i=0;i<totalCol;i++){
            nodes[i]=new node();
            nodes[i].data=i+1;//给循环链表中的值域放入值
            if (i==0)
                head=nodes[i];
            else
                nodes[i-1].next=nodes[i];
        }
        nodes[totalCol-1].next=head;//尾节点与头节点相连,构成循环链表
        return head;
    }


    //开始进行判断
    public void begin(int total){
        int sort=0;//数组中的第几个人
        int n=total;//数组长度
        int m=3;//相隔数量
        m%=n;//取模运算(主要是防止n<m时的操作,比如n=1时)
        node head = createNodes(total);//创建节点
        while (head.next!=head){
            for (int i=1;i<m-1;i++)
                head=head.next;//下移操作
            node temp=head.next;
            System.out.println("第"+(++sort)+"个自杀的为:"+temp.data);
            head.next=temp.next;
            head=head.next;
        }
        System.out.println("第"+(++sort)+"个自杀的为:"+head.data);
    }
}
public class Test {
    public static void main(String[] args) {
        CircularLinkedList circularLinkedList = new CircularLinkedList();
        circularLinkedList.begin(41);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值