java自定义LinkedList:实现单向链表的增删改查和反转

单向链表的节点由两部分组成,一个是值,一个是下一个节点的引用(指针)。

其数据在内存中存储是不连续的,它存储的数据分散在内存中。

单向链表向外暴露的只有一个头节点(Head),对链表的所有操作,都是直接或者间接地通过其头节点来进行的。

添加元素时,在链表头部添加,效率最高。在链表的中间 或尾部添加,效率很低

以下是根据链表的原理进行的简单的实现,不一定严谨和健壮

java实现的代码如下:

public class MyLinkedList<T> implements Iterable<T>  {
	public int size;
	//头结点
	public Node firstNode;
	
	class Node{
		//节点的值
		private T data;
		//节点的后驱节点
		private Node next;
		
		public Node(T data) {
			super();
			this.data = data;
		}
 
		@Override
		public String toString() {
			return "Node [data=" + data + ", next=" + next + "]";
		}
	}
	
	/**
	 * 自定义迭代器
	 */
    private class MyListIterator implements Iterator<T> {
        private int current = 0;
        private Node currNode = head;

        @Override
        public boolean hasNext() {
            return current<size;
        }

        @Override
        public T next() {
            try {

                current++;

             T t = currNode.data;
             if(currNode.next != null){
                 currNode = currNode.next;
             }
             return t;
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return null;
        }

    }
	
	/**
	 * 根据下标获取节点,下标从开始
	 * @param index:获取下标为index的节点;index-1:获取下标为index的前驱节点;index+1:获取下标为index的后驱节点
	 * @return
	 * @throws Exception
	 */
	public Node getNode(int index) throws Exception {
		if(index<0||index>size-1){
			throw new Exception("请传入合法的下标");
		}
		
		int location=0;
		Node temp=firstNode;
		while(temp.next!=null&&location!=index){
			temp=temp.next;
			location++;
		}
		return temp;
	}
	
	/**
	 * 根据节点查找下标,如果有多个相同的节点,返回查找到的第一个
	 */
	public int getIndex (T t){
		if(firstNode!=null){
			//如果第头节点就是要查找的节点,直接返回下标
			if(firstNode.data.equals(t)){
				return 0;
			}
			Node temp=firstNode;
			int location=0;
			//这种判断方式不能判断链表的头节点,所以头结点额外判断
			while(temp.next!=null){
				temp=temp.next;
				location++;
				if(temp.data.equals(t)){
					return location;
				}
				
			}
		}
		
		return -1;
		
	}
	
	/**
	 * 添加新节点,直接添加在链表的头部,然后该节点作为链表的新头结点
	 * @param t
	 */
	public void add(T t){
		Node newNode=new Node(t);
		if(firstNode==null){
			firstNode=newNode;
			size=1;
		}else{
			newNode.next=firstNode;
			firstNode=newNode;
			size++;
			
		}
		
	}
	
	/**
	 * 找到原链表的最后一个节点,然后将新节点加到该节点后面
	 * 效率低,不推荐
	 * @param t
	 */
	public void addNode(T t){
		Node newNode=new Node(t);
		if(firstNode==null){
			firstNode=newNode;
			size=1;
		}else{
			
			Node temp=firstNode;
			while(temp.next!=null){
				temp=temp.next;
			}
			temp.next=newNode;
			size++;
			
		}
	}
	
	/**
	 * 通过下标添加节点(效率很低)
	 * 1,根据下标查找当前节点,2,新节点的下一个节点指向当前节点的下一个节点,3,当前节点的下一个节指向新节点
	 * @param t 值
	 * @param index 下标
	 * @throws Exception
	 */
	public void addNode(T t,int index) throws Exception{
		Node newNode=new Node(t);
		if(firstNode==null){
			firstNode=newNode;
			size=1;
		}else{
			Node temp=getNode(index);
			newNode.next=temp.next;
			temp.next=newNode;
			size++;
		}
	}
	
	
	
	/**
	 * 1.找到下标对应的节点,将其后驱节点的值和next复制到该节点,可以认为该节点被清除了
	 * 2.如果该下标对应的节点没有后驱节点(最后一个节点),那么查找该下标节点的前驱节点,将该前驱节点的next设为null,也可以认为该节点被清除。
	 * @param index
	 * @throws Exception
	 */
	public void deleteNode(int index) throws Exception{
		
		if(firstNode==null){
			size=0;
		    return;
		}else{
			
			Node temp=getNode(index);
			if(temp.next!=null){
				temp.data=temp.next.data;
				temp.next=temp.next.next;
				size--;
			}else{
				
				//查找改下标对应的前驱节点
				Node preNode=getNode(index-1);
				//将前驱节点的next设为null
				preNode.next=null;
				size--;
				System.err.println("preNode是:"+preNode);
			}
 
			
		}
		
	}
	
	/**
	 * 根据值删除对应的节点
	 * @param t
	 * @throws Exception
	 */
	public void deleteNode(T t) throws Exception{
 
			int index=getIndex(t);
			if(index!=-1){
				deleteNode(index);
			}
	}
 
	
	
	/**
	 * 更新某一个下标对应节点的值
	 * @param index 下标
	 * @param newValue 新值
	 * @throws Exception
	 */
	public void update(int index,T newValue) throws Exception{
		
		if(firstNode!=null){
			 Node node= getNode(index);
			 node.data=newValue;
		}
		
	}
	
	/**
	 * 先根据旧节点的值找到对应的下标,同(int index,T newValue)
	 * @param oldValue 旧节点值
	 * @param newValue  新节点值
	 * @throws Exception
	 */
	public void update(T oldValue,T newValue) throws Exception{
		
		if(firstNode!=null){
			 int index=getIndex(oldValue);
			 if(index!=-1){
				 Node node= getNode(index);
				 node.data=newValue; 
			 }
		}
	}
	
	
	
	/**
	 * 链表反转
	 * 原理:然后让当前节点指向上一个节点(反转前当前节点指向的是下一个节点),循环
	 * @return
	 */
	public Node reverse(){
		
		Node pre=null;
		Node cur=firstNode;
		while(cur!=null){
			//临时变量记录当前的下一个节点,后面的循环就是遍历这个临时变量节点
			Node temp=cur.next;
			//当前节点指向上一个节点
			cur.next=pre;
			pre=cur;
			//临时变量的值付赋给当前节点
			cur=temp;
			
		}
		
		this.firstNode=pre;
		return pre;
		
	}
	
	@Override
	public Iterator<T> iterator() {
		// TODO Auto-generated method stub
		return new MyListIterator();
	}
	
	public static void  main(String[] arrgs) throws Exception {
		MyLinkedList<String> myList=new MyLinkedList<String>();
		myList.add("11");
		myList.add("22");
		myList.add("33");
		myList.add("44");
		myList.add("55");
		/*myList.addNode("11");
		myList.addNode("22");
		myList.addNode("33");
		myList.addNode("44");
		myList.addNode("11.5", 3);
		myList.addNode("10.5", myList.size-1);*/
		for (String string : myList) {
			System.err.println(string);
		}
		
		
		//myList.deleteNode(myList.size-1);
		//myList.deleteNode("11");
/*		myList.update("11.5", "2222");
		System.err.println("大小是"+myList.size+myList.firstNode);
		System.err.println("下标是:"+myList.getIndex("11"));
		
		myList.reverse();
		System.err.println("大小是"+myList.size+myList.firstNode);*/
		
	}
}

运行结果:

55
44
33
22
11

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单向链表是由若干个节点组成的,每个节点都包含一个数据域和一个指向下一个节点的指针域。在单向链表中,只能从头节点开始遍历链表,每个节点只能访问其后继节点。下面是用单向链表实现增删改查的代码实现: ```python # 定义单向链表节点类 class ListNode: def __init__(self, val): self.val = val self.next = None # 定义单向链表类 class LinkedList: def __init__(self): self.head = None # 添加节点 def add_node(self, val): new_node = ListNode(val) if not self.head: self.head = new_node else: curr = self.head while curr.next: curr = curr.next curr.next = new_node # 删除节点 def delete_node(self, val): if not self.head: return if self.head.val == val: self.head = self.head.next else: curr = self.head while curr.next: if curr.next.val == val: curr.next = curr.next.next return curr = curr.next # 修改节点 def update_node(self, old_val, new_val): curr = self.head while curr: if curr.val == old_val: curr.val = new_val return curr = curr.next # 查找节点 def search_node(self, val): curr = self.head while curr: if curr.val == val: return True curr = curr.next return False ``` 在上面的代码中,我们定义了一个单向链表节点类 ListNode ,包含一个数据域 val 和一个指向下一个节点的指针域 next 。然后定义了单向链表LinkedList ,包含一个头节点 head 。在 LinkedList 中,我们实现了 add_node() 方法用于添加节点,delete_node() 方法用于删除节点,update_node() 方法用于修改节点,search_node() 方法用于查找节点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值