版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/HeadingAlong/article/details/54783264
链表结构
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的。链表由结点组成。每个结点的构成:元素(数据元素的映象) +引用(指示后继元素存储位置),元素就是存储数据的存储单元,引用就是连接每个结点的地址数据。
何为单链表
单链表是链式存取的结构,想要找到某个数据元素,必须先从第一个或者特指的某个元素向后查找。
代码实现
功能包括:添加数据add, 修改数据update, 删除数据remove,迭代器的实现,重写toString方法。
注意:该链表结构设计时不允许重复元素出现。
package com.it;
import java.util.Iterator;
import com.it.SingleLink.Node;
/**
* 单链表数据结构
* @author Administrator
*
*/
public class SingleLink<T> implements Iterable<T>{
class Node{//创建节点类
private T date;
private Node next;
public Node(T date){
this.date = date;
}
}
private Node head;//头结点
/**
* 添加数据
* @param date
* T数据
* @return
* Boolean类型返回值,true说明添加成功
* false说明添加失败
*/
public boolean add(T date){//添加一个数据
boolean flag = false;
Node newNode = new Node(date);//创建新节点
//链表是否为空
if(head==null){//为空时,使用该数据创建节点,作为头结点
head = newNode;
flag = true;
}else{//不为空,遍历找到尾节点,next节点指向该新节点
Node tailNode = findTailNode();
tailNode.next = newNode;
flag = true;
}
return flag;
}
/**
* 移除数据
* @param date
* @return
*/
public boolean remove(T date){
boolean flag = false;
//遍历链表,找到数据所在的节点
Node dateNode = findNode(date);
//找到前一个节点和后一个节点
Node prevNode = findPrevNode(date);
Node nextNode = dateNode.next;
if(prevNode==null){//说明该数据是头结点
if(nextNode==null){//说明链表只有一个元素
//将头结点置为空
head = null;
flag = true;
}
//将头结点指向下一个节点
head = nextNode;
flag = true;
}else if(nextNode==null){//说明该数据是尾节点
//将前一个节点的next节点置为null
prevNode.next = null;
flag = true;
}else{//这时数据节点处在中间
//将前一个节点的next节点指向nextNode
prevNode.next = nextNode;
flag = true;
}
return flag;
}
/**
* 更新数据
* @param old
* @param newDate
* @return
*/
public boolean update(T old,T newDate){
boolean flag = false;
Node target = findNode(old);//找到要更新的节点(此时拿到的是节点的引用)
if(target==null){
throw new RuntimeException("没有此数据");
}else{//确定节点已经存在
Node existNode = findNode(newDate);
if(existNode!=null){//确定数据唯一
throw new RuntimeException("该数据已经存在,请使用不存在的数据");
}
//修改该数据的date值
target.date = newDate;
flag = true;
}
return flag;
}
/**
* 查找前一个节点
* @param date
* 节点数据
* @return
* Node
*/
private Node findPrevNode(T date) {
//从头开始遍历
Node temp = head;
while(temp!=null){
if(temp.next!=null){
T dat = temp.next.date;
if(date.equals(dat)){
return temp;
}else{
temp = temp.next;//找到下一个节点
}
}
}
return null;
}
/**
* 根据数据内容查找节点
* @param date
* @return
*/
private Node findNode(T date) {
//从头开始遍历
Node temp = head;
while(temp!=null){
T dat = temp.date;
if(date.equals(dat)){
return temp;
}else{
if(temp.next!=null){//不是最后一个节点
temp = temp.next;//找到下一个节点
}else{//是最后一个节点
return null;
}
}
}
return null;
}
/**
* 找到尾节点
* @return
* 尾部节点
*/
private Node findTailNode() {
//从头开始遍历
Node temp = head;
Node tailNode = null;
while(temp!=null){
if(temp.next!=null){//不是最后一个节点
temp = temp.next;//找到下一个节点
}else{//是最后一个节点
tailNode = temp;
break;//跳出循环,将尾节点返回
}
}
return tailNode;
}
@Override
/**
* 重写toString方法
*/
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append('[');
if(head!=null){
Node temp = head;
while(temp!=null){
if(temp.next!=null){//不是最后一个节点
sb.append(temp.date).append(',');
temp = temp.next;//找到下一个节点
}else{//是最后一个节点
sb.append(temp.date).append(']');
break;
}
}
}else
sb.append(']');
return sb.toString();
}
@Override
/**
* 迭代器的实现
* @return
*/
public Iterator<T> iterator() {
return new Iterator<T>() {
Node node = head;//从头结点开始迭代
T date = null;//得到结点的数据
@Override
public boolean hasNext() {
return node!=null;
}
@Override
public T next() {
//先获取到数据
date = node.date;
node = node.next;
return date;
}
@Override
public void remove() {
SingleLink.this.remove(date);
}
};
}
}