zoukankan      html  css  js  c++  java
  • 单链表常见操作

    最近在重新学习数据结构和算法的知识,数据结构和算法问题本身比较枯燥和乏味,而且比较难不容易掌握,但是属于程序员内功的一部分,学习起来容易上瘾。

    1. 单链表定义

    package algorithm.datastructors;
    
    /**
     * 单向链表
     * @author i324779
     */
    public class ListNode {
    
        private int data;
    
        private ListNode next;
    
        public ListNode(int data) {
            this.data = data;
        }
    
        public int getData() {
            return data;
        }
    
        public void setData(int data) {
            this.data = data;
        }
    
        public ListNode getNext() {
            return next;
        }
    
        public void setNext(ListNode next) {
            this.next = next;
        }
    }
    
    

    2, 单链表的一些常见操作

    package algorithm.datastructors;
    
    import java.util.Stack;
    
    /**
     * 单链表的一些操作
     *
     * @author i324779
     */
    public class ListNodeOperation {
    
        /**
         * 找到链表的中间节点
         * 使用两个指针。让第一个指针的移动速度是另一个的两倍。
         * 当第一个指针到达表尾时,另一个指针则指向中间节点。
         * Note:如果链表节点数为奇数,则第(n/2)个节点为中间节点。
         *
         * @param head
         * @return
         */
        ListNode findMiddle(ListNode head) {
            ListNode ptr1x, ptr2x;
            ptr1x = head;
            ptr2x = head;
            int i = 0;
            // 不断循环,直至达到表尾(next后继指针为null,就表示达到最后一个节点)
            while (ptr1x.getNext() != null) {
                if (i == 0) {
                    ptr1x = ptr1x.getNext();
                    i = 1;
                } else {
                    // 两个指针都后移
                    ptr1x = ptr1x.getNext();
                    ptr2x = ptr2x.getNext();
                    i = 0;
                }
            }
            return ptr2x;
        }
    
        /**
         * 从表尾开始输出链表。
         *
         * @param head
         */
        void printListFromEnd(ListNode head) {
            if (head == null) {
                return;
            }
    
            printListFromEnd(head.getNext());
            System.out.println(head.getData());
        }
    
        /**
         * 检查链表的长度是奇数还是偶数。
         * 使用一个在链表中每次向后移动两个节点的指针。
         * 最后,如果指针值为null,那么聊表长度为偶数;
         * 否则指针指向表尾节点,链表长度为奇数。
         *
         * @param head
         * @return
         */
        public int isLinkedListLengthEven(ListNode head) {
            while (head != null && head.getNext() != null) {
                head = head.getNext().getNext();
            }
            if (head == null) {
                return 0;
            } else {
                return 1;
            }
        }
    
        /**
         * 合并两个有序链表为一个新的有序链表。
         *
         * @param node1
         * @param node2
         * @return
         */
        public ListNode mergeList(ListNode node1, ListNode node2) {
            if (node1 == null) {
                return node2;
            }
            if (node2 == null) {
                return node1;
            }
    
            ListNode result;
            if (node1.getData() <= node2.getData()) {
                result = node1;
                result.setNext(mergeList(node1.getNext(), node2));
            } else {
                result = node2;
                result.setNext(mergeList(node2.getNext(), node1));
            }
            return result;
        }
    
        /**
         * 逆置单向链表。
         *
         * @param head 表头
         * @return 逆置后的单向链表。
         */
        ListNode reverseList(ListNode head) {
            ListNode temp = null;
            ListNode nextNode;
    
            while (head != null) {
                nextNode = head.getNext();
                head.setNext(temp);
                temp = head;
                head = nextNode;
            }
    
            return temp;
        }
    
        /**
         * 找到链表的倒数第n个结点
         * 使用一次链表扫描解决问题。
         * 使用两个指针pNthNode和pTemp。
         * 首先,两个指针都指向链表的头结点。仅当pTemp(沿着链表)进行了n次移动后,
         * pNthNode才开始移动。然后两个指针同时移动直至tTemp到达表尾。
         * 这时pNthNode指针所指的结点就是所求的结点,也就是链表的倒数第n个结点。
         *
         * @param head
         * @param nthNode
         * @return
         */
        ListNode nthNodeFromEnd(ListNode head, int nthNode) {
            ListNode pTemp = head;
            ListNode pNnthNode = null;
    
            for (int count = 1; count < nthNode; count++) {
                if (pTemp != null) {
                    pTemp = pTemp.getNext();
                }
            }
    
            while (pTemp != null) {
                if (pNnthNode == null) {
                    pNnthNode = head;
                } else {
                    pNnthNode = pNnthNode.getNext();
                }
    
                pTemp = pTemp.getNext();
            }
            return pNnthNode;
        }
    
        /**
         * 给定两个有序单链表的头指针head1 和head2, 打印两个链表的公共部分。
         *
         * @param head1 有序链表1
         * @param head2 有序链表2
         */
        public void printCommonPart(ListNode head1, ListNode head2) {
            if (head1 == null || head2 == null) {
                System.out.println("Node is null");
                return;
            }
    
            System.out.println("Common Part: ");
            while (head1 != null && head2 != null) {
                if (head1.getData() < head2.getData()) {
                    head1 = head1.getNext();
                } else if (head1.getData() > head2.getData()) {
                    head2 = head2.getNext();
                } else {
                    System.out.println(head1.getData());
                    head1 = head1.getNext();
                    head2 = head2.getNext();
                }
            }
        }
    
        /**
         * 判断是否有环
         *
         * @param head 链表头结点
         * @return 是否有环
         */
        public static boolean isCycle(ListNode head) {
            ListNode p1 = head;
            ListNode p2 = head;
    
            while (p2 != null && p2.getNext() != null) {
                p1 = p1.getNext();
                p2 = p2.getNext().getNext();
    
                if (p1 == p2) {
                    return true;
                }
            }
    
            return false;
        }
    
        /**
         * 逐对逆置链表
         *
         * @param head
         * @return
         */
        private void reversePairRecursive(ListNode head) {
            if (head == null || head.getNext() == null) {
                return;
            }
    
            ListNode cur = head.getNext();
            ListNode pre = head;
            ListNode next;
    
            while (cur != null && cur.getNext() != null) {
                next = cur.getNext().getNext();
                pre.setNext(cur.getNext());
                cur.getNext().setNext(cur);
                cur.setNext(next);
                pre = cur;
                cur = next;
            }
    
        }
    
        /**
         * 判断一个链表是否为回文结构
         *
         * @param head 单链表的头结点
         * @return true:回文结构;false:不是回文结构
         */
        public boolean isPalindrome(ListNode head) {
            Stack<ListNode> stack = new Stack<>();
            ListNode cur = head;
    
            while (cur != null) {
                stack.push(cur);
                cur = cur.getNext();
            }
    
            while (head != null) {
                if (head.getData() != stack.pop().getData()) {
                    return false;
                }
                head = head.getNext();
            }
    
            return true;
        }
    
    
        public static void main(String[] args) {
            ListNodeOperation operation = new ListNodeOperation();
            int i = 1;
            ListNode head = new ListNode();
            head.setNext(null);
            ListNode tmp;
            ListNode cur = head;
    
            for (; i < 8; i++) {
                tmp = new ListNode();
                tmp.setData(i);
                tmp.setNext(null);
                cur.setNext(tmp);
                cur = tmp;
            }
    
            System.out.println("顺序输出:");
            for (cur = head.getNext(); cur != null; cur = cur.getNext()) {
                System.out.print(cur.getData() + " ");
            }
    
            operation.reversePairRecursive(head);
    
            System.out.println("
    逆序输出:");
            for (cur = head.getNext(); cur != null; cur = cur.getNext()) {
                System.out.print(cur.getData() + " ");
            }
        }
    }
    
    
    
  • 相关阅读:
    ubuntu16.04系统安装
    SQL注入之Sqli-labs系列第二十六关(过滤空格、注释符、逻辑运算符注入)和第二十六A
    提权心法(2)提权基本流程
    布尔盲注
    提权心法(1)信息搜集很重要
    POST注入-双注入
    POST型注入-报错注入
    字符型注入
    Web中间件常见安全漏洞总结
    SSRF 从入门到批量找漏洞
  • 原文地址:https://www.cnblogs.com/IcanFixIt/p/10471386.html
Copyright © 2011-2022 走看看