队列的再解

数据有两种基本的存储结构,一种是连续的,用数组实现。一种是不连续的,用链表实现。数组中的数据是有统一的索引值的,方
便查找但是数组的长度是在一开始就必须要定义好的,所以,添加数据有限,并且当数据比较少时,也会比较浪费内存空间。而链
表则是通过节点,一方面存储数据,一方面每个节点指向下一个节点,一环扣一环地实现多个数据的存储。查找时因为没有统一的
索引值而效率较慢,但添加数据和删除数据时确只要改变之多两个节点的存储数据,并且能够节省内存。因此,我们可以根据需要
的不同来决定我们存储方法的选择。

另外,为了实现数据的存储,我现在所接触到最为方便的就是队列了,队列能够实现基本的数据存储、删除、查询和修改功能,而
也能随加入进去的数据的多少来随意变更长度。在之前,以数组实现过基本的队列功能,今天又试了一下用链表来实现队列的功能。

我觉得用链表实现队列的最主要的问题是链表的结构和实现队列的算法。
首先是链表的结构,链表的基本组成单位是节点,每一个节点又由节点存储的数据和指向下一个节点的指针两个部分。由于java中
没有指针这一数据类型,因此,指向下一个节点的指针可以直接由下一个节点来代替,这就 组成了节点类的两个基本属性。我们为了
方便可以直接将属性设为公有的。实际上一个链表就是一个队列,只要实现队列的能够完成的基本方法也就可以当成一个链表来用了。
总之,在我眼里用链表实现的队列实际上就是一个链表,其基本单位也是节点,基本的方法也是数据的增删查改。

这是我的节点类
public class LinkNode {
public Object data;
public LinkNode next;

public LinkNode(Object obj){
this.data=obj;
}

public LinkNode(){
}
}

然后就是实现方法的算法了。我先把代码抄上
/**
* 链表类,实现链表数据的添加,删除,查找和修改
* @author linsy
*
*/
public class MyLink<E> {
private LinkNode root;
private LinkNode last;
private LinkNode next;

/**
* 向链表中添加数据
* @param e 添加的对象
*/
public void add(E e){
LinkNode ln=new LinkNode(e);//构造函数创建节点对象
if(root==null){ //当根节点为空值时,root设为刚创建的节点
this.root=ln;
}else{ //根节点不为空,将尾节点的下一个节点赋给新节点
this.last.next=ln;
}
this.last=ln; //将尾节点赋给新节点
}

/**
* 向指定位置中添加数据
* @param e 添加的对象
* @param index 添加的位置
*/
public void add(E e,int index){
LinkNode ln=new LinkNode(e);//当根节点为空时,调用add()方法
if(index==0){
this.add(e);

}else{/*否则,查找到第index-1个节点,新节点指向index个节点,index-1指向新节点*/
LinkNode temp=this.search(index-1);
ln.next=temp.next;
temp.next=ln;
}
}

/**
* 计算链表长度
* @return 链表的长度值
*/
/*
定义计数器,从根节点开始遍历链表,每访问一个节点即将节点指向下一个节点,计数器加一,最后返回计数器值
*/
public int getCount(){
int count=0;
LinkNode temp=new LinkNode();
temp=root;
while(temp!=null){
temp=temp.next;
count++;
}
return count;
}

/**
* 查找第index个节点
* @param index 要查询的节点在链表中的位置
* @return 返回第index个节点
*/
/* 与取得链表大小的方法类似,遍历链表,当count值达到index时,返回当前节点
*/
public LinkNode search(int index){
if(index>this.getCount()){
System.out.println("查找失败");
return null;
}else{
LinkNode temp=this.root;
//Object e[]=new Object[getCount()];
for(int i=0;i<index;i++){
//e[i]=temp.data;
temp=temp.next;
}
return temp;
}
}

/**
* 删除第index个数据
* @param index 要删除的节点的位置
*/
/* 先查找到第index-1个节点,然后将该节点的指针指向它的下下个节点*/
public void delete(int index){
int count =this.getCount();
LinkNode temp=this.search(index-1);
if(temp.next.next==null){
temp.next=null;
}else{
temp.next=temp.next.next;
}
count--;
}

/**
*
* @return 返回链表数据组成的数组
*
*/
/*通过数组实现,先建立一个同链表一样大小的数组,然后边遍历链表边将节点数据存入数组,最后返回数组*/
public E[] getMyLinkObject(){
LinkNode temp=this.root;
Object e[]=new Object[getCount()];
for(int i=0;i<getCount();i++){
e[i]=temp.data;
temp=temp.next;
}
return (E[]) e;
}
}

遇到的基本问题大致有:
1.空指针异常。在添加和删除方法是特别容易遇到空指针异常的状况,一般都是因为root为空或者next为空,只要弄清楚了空
指针出现的位置,问题还是比较容易解决的。
2.返回链表时到底要返回什么。当然最好的就是返回所有的节点或者节点数据,而实现查询的最好工具是数组,很自然的,只有用
数组返回节点数据。但是返回值又只能有一个,不能在链表的返回方法中直接for循环返回多个节点,而只能返回数组,再在外部
主函数中再逐个输出。
3.泛型。问题还存在着,虽然已经实现了基本功能,但改错都是按系统提示的方法一个一个试才成的。有时间再看一下泛型方面的
东西吧。
4.指针的修改。重点在逻辑关系的理清,没啥好说的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值