首先创建节点类Node. 【java数据结构之单链表类的设计与顺序插入和就地排序算法】单链表是由节点构成,节点类包含两个成员属性,一个是数据元素,一个是下一个节点的对象引用。
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&&jsize)
{
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();
}
}
}
测试程序贴不下了,大家可以自行尝试~数据结构很枯燥,希望自己坚持下去,慢慢学!
推荐阅读
- 笔记|C语言数据结构——二叉树的顺序存储和二叉树的遍历
- C语言学习(bit)|16.C语言进阶——深度剖析数据在内存中的存储
- 数据结构和算法|LeetCode 的正确使用方式
- 先序遍历 中序遍历 后序遍历 层序遍历
- 数据结构|C++技巧(用class类实现链表)
- 数据结构|贪吃蛇代码--c语言版 visual c++6.0打开
- 算法|算法-二分查找
- 数据结构学习指导|数据结构初阶(线性表)
- leetcode题解|leetcode#106. 从中序与后序遍历序列构造二叉树
- java|ObjectOrientedProgramming - 面向对象的编程(多态、抽象类、接口)- Java - 细节狂魔