链表和递归

目录

由节点构成的动态数据结构,链表

 栈的方法接口

基于链表实现的栈 

队列接口

基于链表的队列 

删除链表中全部元素val,不使用虚拟节点 

删除链表中全部元素val,使用虚拟节点 

用递归算法删除链表中所有元素val 

使用递归函数求数组和 


 

  • 由节点构成的动态数据结构,链表

package com.suanfa.linkedlist;

/**
 * 链表,动态数据结构,由节点构成,
 * 如1-2-3-4-5-6 ,每个数字都存放在一个节点类中
 * @author Administrator
 */
public class LinkedList<E> {
	/**
	 * 节点类,包含节点元素和对其他节点的指向
	 * @author Administrator
	 * 
	 */
	private class Node {
		public E e;// 元素
		public Node next;// 节点之间的指针

		public Node(E e, Node next) {
			this.e = e;
			this.next = next;
		}

		public Node(E e) {
			this(e, null);
		}

		public Node() {
			this(null, null);
		}

		@Override
		public String toString() {
			return e.toString();
		}

	}

	private Node dummyHead;// 虚拟头节点,是头结点的前一个节点,用来方便向链表头插入元素
	private int size;// 节点个数

	/**
	 * 构造函数
	 */
	public LinkedList() {
		dummyHead=new Node();
		size = 0;
	}

	/**
	 * 获取链表中的元素个数
	 * 
	 * @return
	 */
	public int getSize() {
		return size;
	}

	/**
	 * 判断链表是否为空
	 * 
	 * @return
	 */
	public boolean isEmpty() {
		return size == 0;
	}

	/**
	 * 在链表头添加新的元素
	 * 
	 * @param e
	 */
	public void addFirst(E e) {
		/*
		// Node node=new Node(e);新建一个节点
		// node.next=head;新节点指向旧链表的头节点
		// head=node;更新链表头
		head = new Node(e, head);
		size++;// 维护元素个数
		*/
		add(0,e);
	}
	/**
	 * 在链表的index(0-based)位置添加新的元素e
	 * 在链表中不是一个常用的操作,练习用:)
	 * @param index
	 * @param e
	 */
	public void add(int index, E e) {
		if (index < 0 || index > size)
			throw new IllegalArgumentException("Add failed. Illegal index.");
       /*//如果位置是0,则是开头位置
		if (index == 0)
			addFirst(e);
		else {
			Node prev = head;
			// 记录一个前标,让标记移动到坐标的前一个节点
			// 把新节点的next指向前标的next,然后把prev的节点的next指向新节点
			for (int i = 0; i < index - 1; i++) {
				prev = prev.next;
			}
			// Node node = new Node(e);
			// node.next = prev.next;
			// prev.next = node;
			prev.next = new Node(e, prev.next);
			size++;
		}*/
		Node prev = dummyHead;
        for(int i = 0 ; i < index ; i ++)
            prev = prev.next;

        prev.next = new Node(e, prev.next);
        size ++;

	}
	/**
	 *在链表末尾添加新的元素e
	 * @param e
	 */
    public void addLast(E e){
        add(size, e);
    }
    
    /**
     *  获得链表的第index(0-based)个位置的元素
     *  在链表中不是一个常用的操作,练习用:)
     * @param index
     * @return
     */
    public E get(int index){

        if(index < 0 || index >= size)
            throw new IllegalArgumentException("Get failed. Illegal index.");
        //当前节点为虚拟节点的下一个节点,也就是真正的链表头
        Node cur = dummyHead.next;
        for(int i = 0 ; i < index ; i ++)
            cur = cur.next;
        return cur.e;
    }
    
    /**获得链表的第一个元素
     * 
     * @return
     */
    public E getFirst(){
        return get(0);
    }

    /**
     *  获得链表的最后一个元素
     * @return
     */
    public E getLast(){
        return get(size - 1);
    }
    
    /**
     *  修改链表的第index(0-based)个位置的元素为e
     *  在链表中不是一个常用的操作,练习用:)
     * @param index
     * @param e
     */
    public void set(int index, E e){
        if(index < 0 || index >= size)
            throw new IllegalArgumentException("Set failed. Illegal index.");

        Node cur = dummyHead.next;
        for(int i = 0 ; i < index ; i ++)
            cur = cur.next;
        cur.e = e;
    }

    /**
     *  查找链表中是否有元素e
     * @param e
     * @return
     */
    public boolean contains(E e){
        Node cur = dummyHead.next;
        while(cur != null){
            if(cur.e.equals(e))
                return true;
            cur = cur.next;
        }
        return false;
    }
    /**
     * 从链表中删除index(0-based)位置的元素, 返回删除的元素
     * 在链表中不是一个常用的操作,练习用:)
     * @param index
     * @return
     */
    public E remove(int index){
        if(index < 0 || index >= size)
            throw new IllegalArgumentException("Remove failed. Index is illegal.");
        //待删除节点的前一个节点
        Node prev = dummyHead;
        for(int i = 0 ; i < index ; i ++)
            prev = prev.next;
        Node retNode = prev.next;
        //让待删除节点的前一个节点指向删除节点的后一个节点
        //把删除节点跳过去
        prev.next = retNode.next;
        //然后让删除的节点指向null,让jvm回收
        retNode.next = null;
        size --;

        return retNode.e;
    }
    
    /**
     *  从链表中删除第一个元素, 返回删除的元素
     * @return
     */
    public E removeFirst(){
        return remove(0);
    }

    /**
     *  从链表中删除最后一个元素, 返回删除的元素
     * @return
     */
    public E removeLast(){
        return remove(size - 1);
    }

    /**
     *  从链表中删除元素e
     * @param e
     */
    public void removeElement(E e){

        Node prev = dummyHead;
        while(prev.next != null){
            if(prev.next.e.equals(e))
                break;
            prev = prev.next;
        }

        if(prev.next != null){
            Node delNode = prev.next;
            prev.next = delNode.next;
            delNode.next = null;
            size --;
        }
    }

    @Override
    public String toString(){
        StringBuilder res = new StringBuilder();

//        Node cur = dummyHead.next;
//        while(cur != null){
//            res.append(cur + "->");
//            cur = cur.next;
//        }
        for(Node cur = dummyHead.next ; cur != null ; cur = cur.next)
            res.append(cur + "->");
        res.append("NULL");

        return res.toString();
    }
    public static void main(String[] args) {

        LinkedList<Integer> linkedList = new LinkedList<Integer>();
        for(int i = 0 ; i < 5 ; i ++){
            linkedList.addFirst(i);
            System.out.println(linkedList);
        }

        linkedList.add(2, 666);
        System.out.println(linkedList);
    }

}
  •  栈的方法接口

package com.suanfa.linkedlist;
/**
 * 栈的方法接口
 * @author Administrator
 *
 */
public interface Stack<E> {
	/**
	 * 查询栈的大小
	 * @return
	 */
	int getSize();
	/**
	 * 判断栈是否为空
	 * @return
	 */
	boolean isEmpty();
	/**
	 * 入栈
	 * @param e
	 */
	void push(E e);
	/**
	 * 出栈
	 * @return
	 */
	E poop();
	/**
	 * 查看栈顶元素
	 * @return
	 */
	E peek();

}
  • 基于链表实现的栈 

 

package com.suanfa.linkedlist;
/**
 * 基于链表实现的栈
 * @author Administrator
 *
 * @param <E>
 */
public class LinkedListStack<E> implements Stack<E> {
	
	private LinkedList<E> list;
	 public LinkedListStack(){
	        list = new LinkedList<E>();
	    }
	/**
	 * 查询栈的大小
	 */
	@Override
	public int getSize() {
		return list.getSize();
	}
	/**
	 * 判断栈是否为空
	 */
	@Override
	public boolean isEmpty() {
		return list.isEmpty();
	}
	/**
	 * 入栈
	 */
	@Override
	public void push(E e) {
		list.addFirst(e);
		
	}
	/**
	 * 出栈
	 */
	@Override
	public E poop() {
		return list.removeFirst();
	}
	/**
	 * 查看栈顶元素
	 */
	@Override
	public E peek() {
		return list.getFirst();
	}
	@Override
	public String toString() {
		StringBuilder res = new StringBuilder();
        res.append("Stack: top ");
        res.append(list);
        return res.toString();
	}
	public static void main(String[] args) {

	        LinkedListStack<Integer> stack = new LinkedListStack<Integer>();

	        for(int i = 0 ; i < 5 ; i ++){
	            stack.push(i);
	            System.out.println(stack);
	        }

	        stack.poop();
	        System.out.println(stack);
	    }
	
	

}
  • 队列接口

 

package com.suanfa.linkedlist;
/**
 * 队列接口
 * @author Administrator
 *
 * @param <E>
 */
public interface Queue<E> {
	int getSize();
	boolean isEmpty();
	void enqueue(E e);
	E dequeue();
	E getFront();

}
  • 基于链表的队列 

package com.suanfa.linkedlist;
/**
 * 基于链表的队列
 * @author Administrator
 *
 * @param <E>
 */
public class LinkedListQueue<E> implements Queue<E> {
	/**
	 * 节点类,包含节点元素和对其他节点的指向
	 * @author Administrator
	 *
	 */
    private class Node{
        public E e;
        public Node next;

        public Node(E e, Node next){
            this.e = e;
            this.next = next;
        }

        public Node(E e){
            this(e, null);
        }

        public Node(){
            this(null, null);
        }

        @Override
        public String toString(){
            return e.toString();
        }
    }
    //声明头节点和尾节点
    private Node head, tail;
    //声明元素的个数
    private int size;
    /**
     * 构造方法
     */
    public LinkedListQueue(){
        head = null;
        tail = null;
        size = 0;
    }
    /**
     * 获取队列元素个数
     */
    @Override
    public int getSize(){
        return size;
    }
    /**
     * 判断队列是否为空
     */
    @Override
    public boolean isEmpty(){
        return size == 0;
    }
    /**
     * 入队
     */
    @Override
    public void enqueue(E e){
    	//当第一个元素入队的时候,头和尾都指向第一个节点
        if(tail == null){
            tail = new Node(e);
            head = tail;
        }
        //否则尾节点指向新节点,并维护尾节点
        else{
            tail.next = new Node(e);
            tail = tail.next;
        }
        size ++;
    }
    /**
     * 出队
     */
    @Override
    public E dequeue(){
    	//如果队列为空,抛出异常
        if(isEmpty())
            throw new IllegalArgumentException("Cannot dequeue from an empty queue.");
        //记录头节点
        Node retNode = head;
        //头节点向尾部移动一位
        head = head.next;
        //队首节点指向null,让JVM回收
        retNode.next = null;
        //如果队列没有节点了,头和尾都变为null
        if(head == null)
            tail = null;
        size --;
        return retNode.e;
    }
    /**
     * 获取队首元素
     */
    @Override
    public E getFront(){
        if(isEmpty())
            throw new IllegalArgumentException("Queue is empty.");
        return head.e;
    }

    @Override
    public String toString(){
        StringBuilder res = new StringBuilder();
        res.append("Queue: front ");

        Node cur = head;
        while(cur != null) {
            res.append(cur + "->");
            cur = cur.next;
        }
        res.append("NULL tail");
        return res.toString();
    }

    public static void main(String[] args){

        LinkedListQueue<Integer> queue = new LinkedListQueue<Integer>();
        for(int i = 0 ; i < 10 ; i ++){
            queue.enqueue(i);
            System.out.println(queue);

            if(i % 3 == 2){
                queue.dequeue();
                System.out.println(queue);
            }
        }
    }
}
  • 删除链表中全部元素val,不使用虚拟节点 

package com.suanfa.linkedlist;

/**
 * 删除链表中全部元素val,不使用虚拟节点
 * 
 * @author Administrator
 * 
 */
public class Solution {
	/**
	 * 节点类
	 * @author Administrator
	 *
	 */
	class ListNode {

		public int val;
		public ListNode next;

		public ListNode(int x) {
			val = x;
		}
	}
	public ListNode removeElements(ListNode head, int val) {
		//如果链表只有一个节点,当节点不为空并且节点的元素是要删除的元素,执行删除
        while(head != null && head.val == val){
            ListNode delNode = head;
            head = head.next;
            delNode.next = null;
        }
        //如果链表为空,返回链表
        if(head == null)
            return head;
        //如果第一个节点不是要删除的节点,向下遍历
        ListNode prev = head;
        while(prev.next != null){
            if(prev.next.val == val) {
                ListNode delNode = prev.next;
                prev.next = delNode.next;
                delNode.next = null;
            }
            else
                prev = prev.next;
        }

        return head;
    }

}
  • 删除链表中全部元素val,使用虚拟节点 

package com.suanfa.linkedlist;

/**
 * 删除链表中全部元素val,使用虚拟节点
 * 
 * @author Administrator
 * 
 */
public class Solution2 {
	/**
	 * 节点类
	 * @author Administrator
	 *
	 */
	class ListNode {

		public int val;
		public ListNode next;

		public ListNode(int x) {
			val = x;
		}
	}
	public ListNode removeElements(ListNode head, int val) {
		//新建一个虚拟节点
		ListNode dummyHead = new ListNode(-1);
		//虚拟节点指向链表头
        dummyHead.next = head;
        //从虚拟节点开始查找需要删除的节点
        ListNode prev = dummyHead;
        while(prev.next != null){
            if(prev.next.val == val)
                prev.next = prev.next.next;
            else
                prev = prev.next;
        }

        return dummyHead.next;
    }

}
  • 用递归算法删除链表中所有元素val 

package com.suanfa.linkedlist;

import com.suanfa.linkedlist.Solution2.ListNode;

/**
 * 用递归算法删除链表中所有元素val
 * 
 * @author Administrator
 * 
 */
public class Solution3 {
	/**
	 * 节点类
	 * @author Administrator
	 *
	 */
	public class ListNode {

		public int val;
		public ListNode next;

		public ListNode(int x) {
			val = x;
		}
		/**
		 * 构造函数,把一个数组转换为一个链表
		 * @param arr
		 */
		public ListNode(int[] arr) {

			if (arr == null || arr.length == 0)
				throw new IllegalArgumentException("arr can not be empty");
			//链表头为数组第一个元素
			this.val = arr[0];
			ListNode cur = this;
			//把数组中其他元素拼接成链表
			for (int i = 1; i < arr.length; i++) {
				cur.next = new ListNode(arr[i]);
				cur = cur.next;
			}
		}

		// 以当前节点为头结点的链表信息字符串
		@Override
		public String toString() {

			StringBuilder s = new StringBuilder();
			ListNode cur = this;
			while (cur != null) {
				s.append(cur.val + "->");
				cur = cur.next;
			}
			s.append("NULL");
			return s.toString();
		}
	}
	/**
	 * 用递归算法删除链表中的所有指定元素
	 * @param head
	 * @param val
	 * @return
	 */
	public ListNode removeElements(ListNode head, int val) {
		//如果链表是空,返回链表或者null
		if (head == null)
			return head;
		/*1->2->6->3->4->5->6
		 * 第一次:1.next=(1)->1.next=2-3-4-5-null 返回最终结果1-2-3-4-5-null
		 * 第二次:2.next=(2)->2.next=3-4-5-null 返回到(1)为2-3-4-5-null
		 * 第三次:6.next=(3)->6.next=3-4-5-null 返回到(2)为3-4-5-null
		 * 第四次:3.next=(4)->3.next=4-5-null 返回到(3)为3-4-5-null
		 * 第五次:4.next=(5)->4.next=5-null 返回到(4)为4-5-null
		 * 第六次:5.next=(6)->5.next=null 返回到(5)为5-null
		 * 第七次:6.next=null->返回到(6)为null
		 * 
		 */
		head.next = removeElements(head.next, val);
		return head.val == val ? head.next : head;
	}

	public static void main(String[] args) {

		int[] nums = { 1, 2, 6, 3, 4, 5, 6 };
		ListNode head =new Solution3().new ListNode(nums);
		System.out.println(head);

		ListNode res = (new Solution3()).removeElements(head, 6);
		System.out.println(res);
	}

}

//通过递归深度和打印输出查看递归过程
/*public class Solution3 {
	
	public class ListNode {

		public int val;
		public ListNode next;

		public ListNode(int x) {
			val = x;
		}

		public ListNode(int[] arr) {

			if (arr == null || arr.length == 0)
				throw new IllegalArgumentException("arr can not be empty");
			//链表头为数组第一个元素
			this.val = arr[0];
			ListNode cur = this;
			//把数组中其他元素拼接成链表
			for (int i = 1; i < arr.length; i++) {
				cur.next = new ListNode(arr[i]);
				cur = cur.next;
			}
		}

		// 以当前节点为头结点的链表信息字符串
		@Override
		public String toString() {

			StringBuilder s = new StringBuilder();
			ListNode cur = this;
			while (cur != null) {
				s.append(cur.val + "->");
				cur = cur.next;
			}
			s.append("NULL");
			return s.toString();
		}
	}

    public ListNode removeElements(ListNode head, int val, int depth) {

        String depthString = generateDepthString(depth);

        System.out.print(depthString);
        System.out.println("Call: remove " + val + " in " + head);

        if(head == null){
            System.out.print(depthString);
            System.out.println("Return: " + head);
            return head;
        }

        ListNode res = removeElements(head.next, val, depth + 1);
        System.out.print(depthString);
        System.out.println("After remove " + val + ": " + res);

        ListNode ret;
        if(head.val == val)
            ret = res;
        else{
            head.next = res;
            ret = head;
        }
        System.out.print(depthString);
        System.out.println("Return: " + ret);

        return ret;
    }

    private String generateDepthString(int depth){
        StringBuilder res = new StringBuilder();
        for(int i = 0 ; i < depth ; i ++)
            res.append("--");
        return res.toString();
    }

    public static void main(String[] args) {

        int[] nums = {1, 2, 6, 3, 4, 5, 6};
        ListNode head = new Solution3().new ListNode(nums);
        System.out.println(head);

        ListNode res = (new Solution3()).removeElements(head, 6, 0);
        System.out.println(res);
    }

}*/
  • 使用递归函数求数组和 

package com.suanfa.linkedlist;
/**
 * 使用递归函数求数组和
 * @author Administrator
 *
 */
public class Sum {
	
	/**
	 * 计算arr[l...n)这个区间内所有数字的和
	 * @param arr
	 * @param l
	 * @return
	 */
	public static int sum(int[]arr,int l){
		if(l==arr.length){
			return 0;
		}
		return arr[l]+sum(arr,l+1);
	}
	public static int sum(int[]arr){
		return sum(arr,0);
	}
	public static void main(String[] args) {
		int[] nums = {1, 2, 3, 4, 5, 6, 7, 8};
        System.out.println(sum(nums));
	}

}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值