线性表(二)--- 单链表

链式存储结构的线性表 简称为链表。是采用一组地址任意的存储单元存放线性表中的元素数据。
它需要在每一个数据元素里保存一个引用下一个数据元素的引用 --- 指针。单链表 --- 每个节点只保留一个引用, 该引用指向当前节点的下一个节点, 没有引用指向头节点, 尾节点的next引用为null。
建立的方法
1.头插法 : 该方法从一个空表开始, 不断创建新节点,将数据元素存入节点的data域中, 然后不断地以新节点为头节点,并让新节点指向原来的头节点。
2.尾插法 : 新节点插入当前链表的表尾上, 因此需要为链表定义一个引用变量来保存链表的最后一个节点。
查找:(1) 找第index个元素:从header节点依次向下在单链表中找第index个节点。 算法:以head为头, current为当前节点(初始时current从header起)0 为头节点序号, i 为计数器 则counter依次下移寻找节点, 并使i 同时递增记录节点序号, 直到返回指定节点。
       (2) 找element元素:找到是否又等于给定element值的节点 有返回相应的索引 ,无返回-1。
插入:element的新节点插入到第index个节点的位置上, 找到index - 1的节点, 生成一个数据域为element的newNode
 使得index -1处的节点的next域指向新的节点, 新节点的next指向原来的index处的节点。
删除:index个节点删除, 先找到引用它的index - 1节点, 然后让index - 1的next指向原来的index  + 1节点 ,释放index处的节点。
 参考代码:
public class LinkList<T> {

	//定义一个节点类
	private class Node{
		//保存数据
		private T data;
		//下一个节点域
		private Node next;
		public Node(){
			
		}
		public Node(T data, Node next){
			this.data = data;
			this.next = next;
		}
	}
	//保存头节点 和 尾节点
	private Node header;
	private Node tail;//trailer   prev域 和 next域  -- 引用域
	//链表中的节点数
	private int size;
	
	//创建空链表
	public LinkList(){
		header = null; 
		tail = null;
	}
	
	//根据指定元素创建链表
	public LinkList(T element){
		header = new Node(element, null);//创建每一个元素是以节点的形式出现的
		tail = header;
		size ++;
	}
	
	//返回链表节点的长度
	public int length(){
		return size;
	}
	
	//查找1 回去index处的节点
	public T get(int index){
		return getNodeByIndex(index).data;
	}
	
	//根据索引获取节点
	private Node getNodeByIndex(int index) {
		
		if(index < 0 || index > size -1){
			throw new IndexOutOfBoundsException("线性表越界");
		}
		Node current = header;
		for(int i = 0; i < size && current != null; i ++, current = current.next){//依次向下寻找节点
			if(i == index){
				return current; 
			}
		}
		return null;
	}
	
	//查找指定的element
	public int locate(T element){
		Node current = header;
		for(int i = 0; i < size && current != null; i ++, current = current.next){//依次向下寻找节点
			if(current.data == element){
				return i; 
			}
		}
		return -1;
	}
	
	//插入数据
	public void insert(T element, int index){
		if(index < 0 || index > size){
			throw new IndexOutOfBoundsException("线性表越界");
		}
		if(header == null){
			add(element);
		}
		else{
			if(index == 0){
				addAtHeader(element);
			}
			else{
				Node preNode = getNodeByIndex(index - 1);
				preNode.next = new Node(element, preNode.next);
				size ++;
			}	
		}	
	}
	
	//头插法
	public void addAtHeader(T element) {
		
		//作为一个新的头
		header = new Node(element, header);
		if(tail == null){
			tail = header;
		}
		size ++;	
	}
	
	//尾插法
	public void add(T element){
		
		//判断是不是空
		if(header == null){
			header = new Node(element, null);
			tail = header;
		}
		else{
			Node newNode = new Node(element, null);
			tail.next = newNode;
			tail = newNode;
		}
		size ++;
	}
	
	//删除数据
	public T delete(int index){
		
		if(index < 0 || index > size -1){
			throw new IndexOutOfBoundsException("线性表越界");
		}
		Node delNode = null;
		//被删除的是头节点
		if(index == 0){
			header = delNode;
            header = header.next;		
		}
		else{
			Node preNode = getNodeByIndex(index - 1);

			delNode = preNode.next;
			preNode = delNode.next;
			//被删除节点的next引用赋值为null
			delNode.next = null;
		}
	   size --;
	   return delNode.data;
	}
	//判断是否为空
	public boolean empty(){
		return size == 0;
	}
	
	//清空列表
	public void clear(){
		header = null; 
		tail = null;
		size = 0;
	}
	
	public String toString(){
		if(size == 0){
			return "[]";
		}
		else{
			StringBuffer sb = new StringBuffer("[");
			for(Node current = header; current != null; current = current.next){
				sb.append(current.data.toString() + ", ");//这里, 后面的空格很重要, 否则输出时可能出错
			}
			int len = sb.length();
			return sb.delete(len - 2, len).append("]").toString();
		}
	}
}
测试部分:
public static void main(String[] args) {
		LinkList<Integer> llist = new LinkList<Integer>();
			llist.insert(1, 0);
			llist.add(2);//尾插法
			llist.add(3);
			System.out.println(llist);
			System.out.println("2在中的位置:" + llist.locate(2));
			llist.addAtHeader(4);
			System.out.println(llist);
			System.out.println("第2个位置的元素是:" + llist.get(2));
		}



参考:《疯狂java突破程序员的基本功的16课》

以上就是这篇的内容,如果存在错误的地方或有可以优化的地方,请您指出,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值