链表

链表

本来关于链表是不准备写这个的,但是呢由于lxj和zyj,还是写一下吧,嗨,人生真难。

写在最前,由于最近在刷leetcode,所以🌰一半是从leetcode中的习题得来

单链表

单链表的定义以及基本操作

// 单链表
class Test{
	// 链表节点类
	public static class ListNode{
		int val;
		ListNode next;
		ListNode(){}
		ListNode(int val){this.val = val;}
		ListNode(int val,ListNode next){this.val = val;this.next = next;};

	}
	public static void main(String[] args) {
		ListNode l1 = new ListNode(1);
		ListNode l2 = new ListNode(2);
		ListNode l3 = new ListNode(3);
		ListNode l4 = new ListNode(4);
		ListNode l5 = new ListNode(5);
		l1.next = l2;
		l2.next = l3;
		l3.next = l4;
		l4.next = l5;
		printLinkedList(l1);
		System.out.println(lenOfLinkedList(l1));
		System.out.println(findNode(l1,3));
		System.out.println(findNode2(l1,7));
		printLinkedList(insertListNode(l1,3,9));
		printLinkedList(deleteListNode(l1,5));
		printLinkedList(reverse(l1));
	}
	// 打印整个链表
	public static void printLinkedList(ListNode head){
		if(head == null) return;
		while(head!=null){
			System.out.print(head.val + " ");
			head = head.next;
		} 
		System.out.println();
	}
	// 求链表长度
	public static int lenOfLinkedList(ListNode head){
		int res = 0;
		while(head!=null){
			res++;
			head = head.next;
		}
		return res;
	}
	// 查找节点操作
	// 按照位置进行查找
	public static int findNode(ListNode head,int k){
		if(head == null || lenOfLinkedList(head) < k) return 0;
		while(k-->1) head = head.next;
		return head.val;
	}
	// 按照值val进行查找
	public static boolean findNode2(ListNode head,int val){
		while(head!=null){
			if(head.val == val) return true;
			head = head.next;
		}
		return false;
	} 
	// 插入节点
	public static ListNode insertListNode(ListNode head,int k,int val){
		if(head == null || lenOfLinkedList(head) < k) return head;
		// 插入节点的关键在于记录插入位置前的那个节点,以及插入位置后的那个节点
		ListNode dummy = new ListNode();
		ListNode cur = head;
		ListNode insertNode = new ListNode(val);
		dummy.next = head;
		// 找到插入节点的位置
		while(k-->1) cur=cur.next;
		// 插入节点
		insertNode.next = cur.next;
		cur.next = insertNode;
		return dummy.next;
	}
	// 删除节点
	public static ListNode deleteListNode(ListNode head,int val){
		if(head == null) return head;
		ListNode dummy = new ListNode();
		dummy.next = head;
		while(head!=null){
			if(head.next!=null && head.next.val == val) head.next = head.next.next;
			head = head.next;
		}
		return dummy.next;
	}
	// 原地翻转链表
	public static ListNode reverse(ListNode head){
		if(head == null || head.next == null) return head;
		ListNode dummy = new ListNode();
		ListNode cur = head;
		ListNode nex = head.next;
		while(cur!=null){
			cur.next = dummy.next;
			dummy.next = cur;
			cur = nex;
			if(nex!=null) nex = nex.next;
		}
		return dummy.next;
	}
}

注:上述代码均通过测试

一般有关于单链表的题型

详情见另外一个博客,🔗如下
链表常见简单题型

双链表

双链表的定义以及基本操作

// 双链表
class Test{
	static class ListNode{
		int val;
		ListNode pre;
		ListNode next;
		ListNode(){}
		ListNode(int val){this.val=val;}
		ListNode(int val,ListNode pre){this.val = val;this.pre = pre;}
		ListNode(int val,ListNode pre,ListNode next){this.val = val;this.next = next;this.pre = pre;}
	}
	public static void main(String[] args) {
		ListNode l1 = new ListNode(1);
		ListNode l2 = new ListNode(2,l1);
		ListNode l3 = new ListNode(3,l2);
		ListNode l4 = new ListNode(4,l3);
		ListNode l5 = new ListNode(5,l4);
		ListNode l6 = new ListNode(6,l5);
		l1.next = l2;
		l2.next = l3;
		l3.next = l4;
		l4.next = l5;
		l5.next = l6;
		printListNode(l1);
		printListNode(insert(l1,3,9));
		printListNode(delete(l1,9));
	}
	// 打印双向链表
	public static void printListNode(ListNode head){
		while(head!=null){
			System.out.print(head.val+" ");
			head=head.next;
		}
		System.out.println();
	}
	// 求长度
	public static int len(ListNode head){
		int res = 0;
		while(head !=null){
			res++;
			head=head.next;
		}
		return res;
	}
	// 插入
	public static ListNode insert(ListNode head,int k,int val){
		if(head == null || len(head) < k) return head;
		ListNode dummy = new ListNode();
		dummy.next = head;
		head.pre = dummy;
		while(k-->1) head = head.next;
		ListNode cur = new ListNode(val);
		cur.next = head.next;
		head.next.pre = cur;
		head.next = cur;
		cur.pre = head;
		return dummy.next;

	}
	// 删除
	public static ListNode delete(ListNode head,int val){
		if(head == null) return head;
		ListNode dummy = new ListNode();
		dummy.next = head;
		head.pre = dummy;
		while(head!=null){
			// 找到了要删除的节点,要删除的节点上一个节点是head
			if(head.next!=null && head.next.val == val){
				head.next = head.next.next;
				head.next.next.pre = head;
				break;
			}
			head= head.next;
		}
		return dummy.next;
	} 
}

注:上述代码均通过测试

一般有关于双向链表的题型

剑指 Offer 36. 二叉搜索树与双向链表

题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。

/*
// Definition for a Node.
class Node {
    public int val;
    public Node left;
    public Node right;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val,Node _left,Node _right) {
        val = _val;
        left = _left;
        right = _right;
    }
};
*/
class Solution {
    Node pre, head;
    public Node treeToDoublyList(Node root) {
        if(root == null) return null;
        dfs(root);
        head.left = pre;
        pre.right = head;
        return head;
    }
    void dfs(Node cur) {
        if(cur == null) return;
        dfs(cur.left);
        if(pre != null) pre.right = cur;
        else head = cur;
        cur.left = pre;
        pre = cur;
        dfs(cur.right);
    }
}

循环链表

循环单链表

// 循环单链表
class Test{
	// 链表节点类
	public static class ListNode{
		int val;
		ListNode next;
		ListNode(){}
		ListNode(int val){this.val = val;}
		ListNode(int val,ListNode next){this.val = val;this.next = next;};

	}
	public static void main(String[] args) {
		ListNode l1 = new ListNode(1);
		ListNode l2 = new ListNode(2);
		ListNode l3 = new ListNode(3);
		ListNode l4 = new ListNode(4);
		ListNode l5 = new ListNode(5);
		l1.next = l2;
		l2.next = l3;
		l3.next = l4;
		l4.next = l5;
		// 成为循环链表的重要操作
		l5.next = l1;
	}
}

循环双链表

class Test{
	static class ListNode{
		int val;
		ListNode pre;
		ListNode next;
		ListNode(){}
		ListNode(int val){this.val=val;}
		ListNode(int val,ListNode pre){this.val = val;this.pre = pre;}
		ListNode(int val,ListNode pre,ListNode next){this.val = val;this.next = next;this.pre = pre;}
	}
	public static void main(String[] args) {
		ListNode l1 = new ListNode(1);
		ListNode l2 = new ListNode(2,l1);
		ListNode l3 = new ListNode(3,l2);
		ListNode l4 = new ListNode(4,l3);
		ListNode l5 = new ListNode(5,l4);
		ListNode l6 = new ListNode(6,l5);
		l1.next = l2;
		l2.next = l3;
		l3.next = l4;
		l4.next = l5;
		l5.next = l6;
		
		// 成为循环链表的操作
		l6.next = l1;
		l1.pre = l6;
	}
}

一般有关于循环链表的题型

如上 剑指 Offer 36. 二叉搜索树与双向链表

静态链表

概念:

静态链表借助于数组来描述线性表的链式存储结构 ,节点也有数据域data和指针域next,与前面的所讲述的链表不同的是,这里的指针指向的节点的相对地址(数组的下标,又称为游标),和顺序表(数组)一样,静态链表也需要预先分配一块内存空间。一般而言,静态链表以\(next==-1\)结束。

posted @ 2020-11-21 16:49  BOTAK  阅读(68)  评论(0编辑  收藏  举报