线性表之链式存储结构

本文介绍了线性表的链式存储结构,探讨了其特点如灵活性和低存储密度,以及如何手动实现单链表类SingleLinkedList,包括核心方法add的实现。实例演示了如何创建并操作单链表,适合初学者理解链式数据结构的原理。
摘要由CSDN通过智能技术生成

线性表之链式存储结构

特点:
数据元素存储在不连续的存储空间。每个节点是由数据域和指针域组成。元素之间的逻辑关系通过存储节点之间的链接关系反映出来。
缺点:

  1. 比顺序存储结构的存储密度小(每个节点都由数据域和指针域组成,所以相同空间内假设全存满的话顺序存储比链式存储更多)。
  2. 查找节点时链式存储要比顺序存储慢(每个节点地址不连续、无规律、导致查找效率低下)。

优点:

  1. 插入、删除灵活(不必移动节点,只要改变节点中的指针,但是需要先定位到节点上)。
  2. 有元素才会分配节点空间,不会有闲置的节点。

手写LinkedList集合:

注意:java.util.LinkedList是双向链表,这里手写的LinkedList是单链表。

package com.bjsxt.datastructure.linetable;
/**
 * 线性表接口
 * 和存储结构无关
 * @author Administrator
 *
 */
public interface List {
	// 返回线性表的大小,即数据元素的个数。
	public int size();
	
	// 返回线性表中序号为 i 的数据元素
	public Object get(int i);

	// 如果线性表为空返回 true,否则返回 false。
	public boolean isEmpty();

	// 判断线性表是否包含数据元素 e
	public boolean contains(Object e);

	// 返回数据元素 e 在线性表中的序号
	public int indexOf(Object e);

	// 将数据元素 e 插入到线性表中 i 号位置
	public void add(int i, Object e);

	// 将数据元素 e 插入到线性表末尾
	public void add(Object e);

	// 将数据元素 e 插入到元素 obj 之前
	public boolean addBefore(Object obj, Object e);

	// 将数据元素 e 插入到元素 obj 之后
	public boolean addAfter(Object obj, Object e);

	// 删除线性表中序号为 i 的元素,并返回之
	public Object remove(int i);

	// 删除线性表中第一个与 e 相同的元素
	public boolean remove(Object e);

	// 替换线性表中序号为 i 的数据元素为 e,返回原数据元素
	public Object replace(int i, Object e);

	
}

Node.java:

package com.bjsxt.datastructure.linetable;
/**
 * 单链表的结点 
 * @author Administrator
 *
 */
public class Node {
    //这里没有使用private是因为,可以直接通过点属性进行操作,注意这几个类在同一个包中
	Object data;//要存储的数据
	Node  next; //指向下一个节点
	public Node() {
		
	}
	public Node(Object data) {
		super();
		this.data = data;
	}
	public Node(Object data, Node next) {
		super();
		this.data = data;
		this.next = next;
	}

}

SingleLinkedList.java( 主要看add函数的实现):

package com.bjsxt.datastructure.linetable;

public class SingleLinkedList implements List{

	private Node head = new Node();//头结点,不存储数据,为了编程方便
	
	private int size;//一共有几个结点
	
	@Override
	public int size() {
		
		return size;
	}

	@Override
	public Object get(int i) {
		//可就和顺序表不一样了,不能通过索引直接计算定位,而需要从头结点开始进行查找
		Node p = head;
		for(int j = 0;j<=i;j++){
			p = p.next;
		}
		return p.data;
	}

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

	@Override
	public boolean contains(Object e) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public int indexOf(Object e) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void add(int i, Object e) {
		//如果i位置错误报异常
		if(i <0  || i> size){
			throw new MyArrayIndexOutOfBoundsException("数组指针越界异常:"+i);
		}
		
		//找到前一个结点,从head结点开始
		Node p = head;
		for(int j = 0;j<i;j++){
			p = p.next;
		}
		//新创建一个结点
		//Node newNode = new Node(e);
		Node newNode = new Node();
		newNode.data = e;
		//newNode.next = null;
		//指明新结点的直接后继结点
		newNode.next = p.next;
		
		//指明新结点的直接前驱结点
		p.next = newNode;
		
		//size++
		size++;
	}

	@Override
	public void add(Object e) {
		this.add(size, e);
		
	}

	@Override
	public boolean addBefore(Object obj, Object e) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean addAfter(Object obj, Object e) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public Object remove(int i) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean remove(Object e) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public Object replace(int i, Object e) {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	public String toString() {
		if(size == 0){
			return "[]";
		}
		StringBuilder builder = new StringBuilder("[");
		Node p = head.next;
		for(int i=0;i<size;i++){
			if(i !=size -1){
				builder.append(p.data+",");
			}else{
				builder.append(p.data);
			}
			//移动指针到下一个结点
			p  = p.next;
			
		}
		builder.append("]");
		return builder.toString();
	}

}

TestSingleList.java:

package com.bjsxt.datastructure.linetable;

public class TestSingleLinkedList {

	public static void main(String[] args) {
		
		List list = new SingleLinkedList();
		
		list.add(123);
		list.add(321);
		list.add(456);
		list.add(678);
		list.add(789);
		list.add(111);
		list.add(222);
		
		list.add(10, 666);
		
		System.out.println(list.size());
		System.out.println(list.isEmpty());
		System.out.println(list.get(5));
		System.out.println(list.toString());
	}

}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值