数据结构(Java)---线性表

大概有十几天没写博客了,没人看也是很伤心的,TAT。大三对计算机考研的内容由了一定的了解。并且:算法+数据结构=程序。所以想重新学习数据结构,不多说,入正题。


线性表

线性表是由n(n>=0)个数据元素所构成的有限序列,通常表示为(a0,a1,…,ai,…an-1)。
线性表有两种基本形式:顺序表和链表(链表有多种形式),他们各有各的特点。当线性表的长度变化比较大或者难以估计,宜用链表。但在长度可以预计并且变化较小的话,宜用顺序表。对线性表按序号访问数据元素时,顺序表要优于链表。在线性表做插入和删除操作时,链表要优于顺序表。所以对顺序表和单链表的选择,视实际情况而定。
线性表的数据接口(Java)应包含如下方法(主要):

public interface List {
    public void clear();   //清空
    public boolean isEmpty();//判断线性表是否为空
    public int length();//返回线性表的长度
    public Object get(int i) throws Exception;//返回第i个元素
    public void insert(int i,Object x) throws Exception;
    public void insert(Object x) throws Exception;    //尾插入
    public void remove(int i) throws Exception;//删除第i个元素
    public int indexOf(Object x);//查找x元素
    public void display();//输出各个元素的值
}

顺序表

顺序表中的元素是在数组中保存的,初始化后空间存储大小是一定的,所以在插入中增加了扩容方法(如果元素再插入要溢出)

package gzy;
public class SqList implements List{
    private Object[] element;       //顺序表元素存储位置
    private int curLen;             //顺序表的长度
    public SqList(int size){
        element=new Object[size];
        curLen=0;
    }
    @Override
    public void clear() {
        curLen=0;
    }
    @Override
    public boolean isEmpty() {
        return curLen==0;
    }
    @Override
    public int length() {
        return curLen;
    }
    public Object get(int i) throws Exception {
        if(i<0||i>curLen)
            throw new Exception("第"+i+"个元素不存在");
        return element[i];
    }
    @Override
    public void insert(int i, Object x) throws Exception{
        if(curLen==element.length){              //扩容
            Object[] listElem=element;
            element=new Object[curLen+1];
            for(int j=0;j<listElem.length;j++)
                element[j]=listElem[j];
        }
        if(i<0||i>curLen){
            throw new Exception("i位置不合法");
        }
        for(int k=curLen;k>i;k--)
            element[k]=element[k-1];
        element[i]=x;
        curLen++;
    }
    @Override
    public void insert(Object x) throws Exception{
        insert(curLen,x);
    }
    @Override
    public void remove(int i) throws Exception{
        if(i<0||i>curLen)
            throw new Exception("i的位置不合法");
        for(int j=i;j<curLen-1;j++)
            element[j]=element[j+1];
        curLen--;
    }
    @Override
    public int indexOf(Object x) {
        for(int i=0;i<curLen;i++){
            if(element[i].equals(x))
                return i;
        }
        return-1;
    }
    @Override
    public void display() {
        for(int i=0;i<curLen;i++)
            System.out.print(element[i]+" ");
        System.out.println();
    }
}

单链表

单链表中需要一个结点类(当然你完全可以直接把结点类当成一个链表)
并且需要一个头结点:头结点的好处是在插入中不需要分情况进行判断

package gzy;

//结点类
     class Node{
        public Object data;
        public Node next;
        public Node(){
            this.data=null;
            this.next=null;
        }
        public Node(Object data){
            this.data=data;
            this.next=null;
        }
        public Node(Object data,Node next){
            this.data=data;
            this.next=next;
        }
    }
public class LinkedList implements List{

    Node head;   //头结点
    public LinkedList(){
        this.head=new Node();
    }
    @Override
    public void clear() {
        this.head=null;
    }
    @Override
    public boolean isEmpty() {
        return this.head.next==null;
    }
    @Override
    public int length() {
        int l=0;
        Node p=head.next;
        while(p!=null){
            l++;
            p=p.next;
        }
        return l;
    }
    @Override
    public Object get(int i) throws Exception {
        int j=0;
        Node p=head.next;
        while(p!=null&&j<i){
            p=p.next;
            j++;
        }
        if(i!=j)
            throw new Exception("第"+i+"个元素不存在");
        return p.data;
    }
    @Override
    public void insert(int i, Object x) throws Exception {
        Node p=head;
        int j=0;
        //寻找前驱结点
        while(p.next!=null&&j<i){
            p=p.next;
            j++;
        }
        if(i!=j)
            throw new Exception("插入位置不合法");
        p.next=new Node(x,p.next);
    }

    @Override
    public void insert(Object x) throws Exception {
        insert(this.length(),x);
    }
    @Override
    public void remove(int i) throws Exception {
        int j=0;
        Node p=head;
        while(p.next!=null&&j<i){
            p=p.next;
            j++;
        }
        if(i!=j)
            throw new Exception("删除位置不合法");
        p.next=p.next.next;

    }
    @Override
    public int indexOf(Object x) {
        int j=0;
        Node p=head.next;
        while(p!=null&&!p.data.equals(x)){
            p=p.next;
            j++;
        }
        if(p!=null)
            return j;
        return -1;
    }
    @Override
    public void display() {
        Node p=head.next;
        while(p!=null){
            System.out.print(p.data+" ");
            p=p.next;
        }
        System.out.println();
    }
}

单链表的种类有很多,(循环单链表,双链表,循环双链表),此处在举一个循环单链表的例子

循环单链表

在实现循环链表时,可以使用头或尾指针去标识它。因为尾指针访问头尾结点时间复杂度都为O(1),所以实际中,仅仅使用尾指针来标识。此处合并两个循环单链表使用了尾指针,时间复杂度为O(1)。

package gzy;

public class CircularList implements List{
    Node head;
    public CircularList(){
        head=new Node();
        head.next=head;
    }
    @Override
    public void clear() {
        head.next=head;
    }
    @Override
    public boolean isEmpty() {
        return this.head.next==head;
    }
    @Override
    public int length() {
        int l=0;
        Node p=head.next;
        while(p!=head){
            l++;
            p=p.next;
        }
        return l;
    }
    @Override
    public Object get(int i) throws Exception {
        while(i<0||i>this.length()-1)
            throw new Exception("i位置不符合");
        int j=0;
        Node p=head.next;
        while(j<i){
            p=p.next;
            j++;
        }
        return p.data;
    }
    @Override
    public void insert(int i, Object x) throws Exception {
        while(i<0||i>this.length())
            throw new Exception("插入位置不符合");
        Node p=head;
        int j=0;
        //寻找前驱结点
        while(j<i){
            p=p.next;
            j++;
        }
        p.next=new Node(x,p.next);
    }
    @Override
    public void insert(Object x) throws Exception {
        insert(this.length(),x);
    }
    @Override
    public void remove(int i) throws Exception {
        int j=0;
        Node p=head;
        while(p.next!=head&&j<i){
            p=p.next;
            j++;
        }
        if(i!=j)
            throw new Exception("删除位置不合法");
        p.next=p.next.next;

    }
    @Override
    public int indexOf(Object x) {
        int j=0;
        Node p=head.next;
        while(p!=head&&!p.data.equals(x)){
            p=p.next;
            j++;
        }
        if(p!=head)
            return j;
        return -1;
    }
    @Override
    public void display() {
        Node p=head.next;
        while(p!=head){
            System.out.print(p.data+" ");
            p=p.next;
        }
        System.out.println();
    }
    public Node getLastNode(){
        Node p=head.next;
        while(p.next!=head)
            p=p.next;
        return p;
    }
    public void merge(CircularList list){
        this.getLastNode().next=list.head.next;
        list.getLastNode().next=this.head;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值