java数据结构之单链表类的设计与顺序插入和就地排序算法

首先创建节点类Node.

单链表是由节点构成,节点类包含两个成员属性,一个是数据元素,一个是下一个节点的对象引用。

class Node
{
      private Object element;//数据元素
      private Node next;//下一个节点的对象引用
      Node(Node next)//头节点构造函数
      {
          this.element=null;
          this.next=next;
      }
      Node(Object element,Node next)//一般节点构造函数
      {
          this.element=element;
          this.next=next;
      }
      public Object getElement() {
          return element;
      }
      public void setElement(Object element) {
          this.element = element;
      }
      public Node getNext() {
          return next;
      }
      public void setNext(Node next) {
          this.next = next;
      }
      public String toString()
      {
          return element.toString();
      }
}

其次创建单链表类

单链表类成员变量包含 头节点、当前节点、链表中数据元素个数。

class SingList
{
    Node head;//头节点
    Node current;//当前节点
    private int size;//链表内数据总数

    public void setSize(int i)//设置链表长度
    {
        this.size=i;
    }

    SingList()//空链表构造函数,当前节点和头节点是同一个节点,且指向的新节点为空,所以用new Node(null)
    {
        this.head=this.current=new Node(null);//构造函数里加一句:head.next=head;在index函数里把循环条件“current!=null”改为“current!=head”即可转化为循环链表
        size=0;
    }

    public void index(int i) throws Exception//定位到当前节点,即将链表中第i个节点作为当前节点
    {
        if(i<-1||i>size-1)//这里判断条件是i<-1,而不是i<0,是因为后面insert函数里的需要。
        {
            throw new Exception("参数有误!");
        }
        if(i==-1)
        {
            current=head;
            return;
        }

        int j=0;
        current=head.getNext();//将当前节点设置为头结点指向的第一个节点
        while(current!=null&&j//循环将执行i次
        {
            current=current.getNext();
            j++;

        }   
    }

    public void insert(int i,Object obj) throws Exception//插入数据
    {
        if(i<0||i>size)
        {
            throw new Exception("参数有误!");
        }
            index(i-1);//把当前节点设置为插入点的前一个节点
            current.setNext(new Node(obj,current.getNext()));
            size++; 
    }

    public Object delete(int i) throws Exception//删除
    {
        if(size==0)
        {
            throw new Exception("链表已空!");
        }
        if(i<0||i>size-1)
        {
            throw new Exception("参数有误!");
        }
        index(i-1);
        Object o=current.getNext().getElement();
        current.setNext(current.getNext().getNext());
        size--;
        return o;
    }

    public Object getDate(int i) throws Exception//获取某个节点的数据
    {
        if(size==0)
        {
            throw new Exception("链表已空!");
        }
        if(i<0||i>size-1)
        {
            throw new Exception("参数有误!");
        }
        index(i);
        return current.getElement();
    }

    public int size()
    {
        return size;
    }

    public boolean isEmpty()
    {
        return size==0;
    }

    public void add(Object o) throws Exception//向链表中添加数据
    {
        if(size==0)
        {
            current.setNext(new Node(o,null));
            size++;
        }
        else
        {
            index(size-1);
            current.setNext(new Node(o,null));
            size++;
        }

    }
}

顺序插入方法

设计思想:从单链表的第一个数据开始,逐个比较每个节点的数据元素与要插入的数据,当节点数据小于插入数据时,进行下一个节点的比较,否则,就找到了插入位置。如果是比较到最后一个节点仍然满足节点数据小于插入数据,则数据插入在链表结尾处。
这里,我先创建了一个的比较器类,实现了Comparator接口,重写了compare方法。

/**
 * 定义自己的比较器
 */
class MyComparator implements Comparator
{

    @Override
    public int compare(Object o1, Object o2) {
        // TODO Auto-generated method stub
        if((o1 instanceof Integer)&&(o2 instanceof Integer))
        {
            Integer i1=(Integer)o1;
            Integer i2=(Integer)o2;
            int a=i1.intValue();
            int b=i2.intValue();
            if(i1>=i2)
                return 1;
            else
                return -1;
        }
        else
        {
            return 0;
        }   
    }
}

然后新建了InsertSorted类,里面只定义了有序插入的静态方法。

class InsertSorted{
    public static void orderInsert(SingList sl,Object o,MyComparator mc){
        Node curr;//当前节点
        Node pre;//前一个节点

        curr=sl.head.getNext();//初始当前节点为第一个节点
        pre=sl.head;//初始前节点为头结点

        while(curr!=null&&mc.compare(curr.getElement(), o)==-1)//循环判断条件:当前节点值不为空且当前节点值小于插入值
        {
            pre=curr;
            curr=curr.getNext();//进行下一个节点的判断,直到找出插入位置

        }
        Node temp=new Node(o,pre.getNext());
        pre.setNext(temp);//完成插入
        sl.setSize(sl.size()+1);        
    }
}

就地插入方法

设计思想:借助有序插入算法,先将原链表数据清空,只保留一个头结点,然后将原链表数据一个个重新有序插入链表,则可以在不创建新节点空间的前提下完成链表的排序。

/**
 * 就地排序
 */
class Sorted{
    public static void SortList(SingList sl,MyComparator cm)
    {
        Node curr;//定义当前节点
        curr=sl.head.getNext();//将头节点指向的第一个数据节点赋值给当前节点
        sl.head.setNext(null);//将原链表清空,仅保留头结点
        sl.setSize(0);//链表长度设为0,即无数据节点
        while(curr!=null)//当前节点为空时,说明原链表全部数据插入完毕,退出循环
        {
            InsertSorted.orderInsert(sl, curr.getElement(), cm);
            curr=curr.getNext();
        }
    }
}

测试程序贴不下了,大家可以自行尝试~数据结构很枯燥,希望自己坚持下去,慢慢学!

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