算法与数据结构【Java】:普通单向链表

普通单向链表应该包含的数据和方法:

结点类(Node):


    属性:
        AnyType value;    //任意类型的数据
        Node* next;        //指向下一个节点的指针
    方法:
        构造方法 Node(AnyType* value, Node* next);

链表类(LinkedList):


    Node* head;        //链表头结点的指针
    Node* tail;        //链表尾结点的指针,可选
    int length;        //链表长度,可选

    int isEmpty();    //链表是否为空
    int contains();    //链表是否包含某个值
    void addToHead(AnyType value);    //向链表头添加数据
    void addToTail(AnyType value);    //向链表尾添加数据
    void addNode(AnyType value, int index)    //向链表指定下标处添加数据
    int deleteFromHead();    //从链表头删除一个数据,返回被删除的数据
    int deleteFromTail();    //从链表尾删除一个数据,返回被删除的数据
    int deleteNode();    //删除指定下标处的数据,返回被删除的数据

 

实现每种方法的思路:


    1、因为LinkedList类的属性有:head,tail,length
        所以要根据不同情况更新三个属性
    2、所以每种方法,都要处理:
        1)head发生变化
        2)tail发生变化
        的情况

下方是Java代码:


//链表类
public class LinkedList {
	//
	Node head;	//链表头结点的指针
	Node tail;	//链表尾结点的指针,可选
	int length;	//链表长度,可选
	
	int isEmpty() {			//链表是否为空
		//头结点为空,链表为空
		return head == null ? 1 : 0;	
	};	
	
	int contains(int value) {		//链表是否包含某个值
		//遍历链表,查找值
		for (Node now=head; now!=null; now=now.next)
			if (now.value == value)
				return 1;
		return 0;
	}
	
	void addToHead(int value) {		//向链表头添加数据
		//如果链表为空,更新head和tail
		if (head == null) 
			head = tail = new Node(value);
		//否则直接添加
		else 
			this.head = new Node(value, this.head);
		this.length++;
	}
	
	void addToTail(int value) {		//向链表尾添加数据
		//如果链表为空,更新head和tail
		if (head == null)
			head = tail = new Node(value);
		//否则直接添加
		else 
			tail = tail.next = new Node(value);
		length++;
	}
	
	void addNode(int value, int index) {	//向链表指定下标处添加数据
		//如果要添加的下标不合法,直接返回
		if (index <= 0) return;
		//如果链表为空,且在第一个位置插入
		if (head == null && index == 1) {
			head = tail = new Node(value);
			length++;
			return ;
		}
		//如果链表为空,要在非法位置插入
		else if (head == null && index != 1) {
			return ;
		}
		//如果在头部插入,更新head
		if (index == 1) {
			head = new Node(value, head);
			length++;
			return ;
		}
		//在其他部位插入
		Node aheadOfAdd = null;
		int cnt = 1;
		//循环查找链表,找到index-1位置的结点,存入aheadOfAdd
		//使得循环停止的条件有两个:
			//情况1:aheadOfAdd=null单独成立,说明要添加的序号已经超出现有的链表长度
			//情况2:cnt+1=index成立且aheadOfAdd为空,说明要插入的位置刚好在链表尾向后第二个位置
			//情况3:cnt+1=index单独成立,说明找到了要插入的结点的前一个结点
		for (aheadOfAdd=head,cnt=1; aheadOfAdd!=null&&cnt+1<index; cnt++,aheadOfAdd=aheadOfAdd.next);
		//System.out.println(cnt);
		//System.out.println(aheadOfAdd);
		//情况1
		if (index != cnt+1) 
			return ;
		//情况2
		if (aheadOfAdd == null) 
			return ;

		//情况3
		aheadOfAdd.next = new Node(value, aheadOfAdd.next);
		length++;
		if (aheadOfAdd.next.next == null) tail = aheadOfAdd.next;
	}
		
	int deleteFromHead() {	//从链表头删除一个数据,返回被删除的数据
		int deletedValue = -1;
		//链表为空,直接返回
		if (head == null) 
			return -1;
		deletedValue = head.value;
		//链表只有一个元素,删除并更新head和tail
		if (head == tail) 
			head = tail = null;
		//删除头部
		else 
			head = head.next;
		length--;
		return deletedValue;
	}
	int deleteFromTail() {	//从链表尾删除一个数据,返回被删除的数据
		int deletedValue = -1;
		//链表为空,直接返回
		if (head == null)
			return -1;
		//链表只有一个元素,删除并更新head和tail
		if (head == tail) {
			deletedValue = head.value;
			head = tail = null;
		}
		//删除尾部
		else {
			Node now = null;
			//遍历找到尾部
			for (now = head; now.next!=tail; now=now.next);
			deletedValue = now.next.value;
			now.next = null;
			tail = now;
		}
		length--;
		return deletedValue;
	}
	
	int deleteNode(int index) {	//删除指定下标处的数据,返回被删除的数据
		//下标不合法,直接返回
		if (index <= 0) return -1;
		int deletedValue = -1;
		int cnt = 1;
		Node now = null;
		//链表为空,直接返回
		if (head == null) 
			return -1;
		//链表只有一个结点且要删除那个结点
		if (head == tail && index == 1) {
			deletedValue = head.value;
			head = tail = null;
		}
		//如果要删除第一个结点,那么下方循环将会出现问题,所以单独处理
		if (index == 1) {
			deletedValue = head.value;
			head = head.next;
		}
		else {
			//循环找到要删除的那个结点
			//循环终止的条件有两个
				//情况1:now==null成立,找到要删除的结点之前已经到了链表尾
				//情况2:cnt+1=index成立,找到了要删除的结点的前一个结点
			for(now=head; cnt+1<index && now!=null; cnt++,now=now.next);
			//情况1
			if(now == null) return -1; 
			//情况2
			deletedValue = now.next.value;
			if (now.next == tail)
				tail = now;
			now.next = now.next.next;
		}
		
		length--;
		return deletedValue;
		
	}
	//转换为字符串方便显示
	public String toString() {
		StringBuilder sb = new StringBuilder("LinkedList: [");
		for (Node now = head; now!=null; now=now.next) {
			sb.append(now.value + ", ");
		}
		sb.append("]");
		if (head != null)
			sb.append("\n\t\t@ StartValue: " + head.value 
					+ "; TailValue: " + tail.value
					+ "; Length: " + length);
		return sb.toString();
	}
	
	//打印链表内容
	void printSelf() {
		System.out.println(this.toString());
	}
	
	//测试函数
	static public void main(String[] argv) {
		LinkedList list = new LinkedList();
		list.addToHead(1);list.addToHead(2);list.addToHead(5);list.printSelf();
		//list.deleteFromHead();list.deleteFromTail();list.printSelf();
		list.addNode(12, 1);list.printSelf();
		list.deleteNode(1);list.printSelf();
		//System.out.println(list.contains(5));
		//System.out.println(list.isEmpty());
	}
	
	
	
}
//链表的结点
class Node{
	int value;	//节点的值
	Node next;	//下一个结点的指针
	
	//两个构造函数
	public Node(int value) {
		this.value = value;
		this.next = null;
	}
	public Node(int value, Node next) {
		this.value = value;
		this.next = next;
	}
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值