数据结构与算法基础 之 链表

数据结构算法基础 之 链表(单链表)

 

  1. 相较于数组,链表这个数据结构可能要复杂一些.
    与数组相比 , 链表在内存上不是连续内存空间 , 是一些零散的内存块 , 通过指针来访问 .
    这就要求链表的每一个节点都要有: 1. 指向下一个节点的指针. 2. 该节点可以存放的数据.

     
  2. java代码实现
     
    /**
     * 链表节点
     */
    
    public class Node {
    
        int num;
    
        Node next;
    
        public Node(int num) {
            this.num = num;
        }
    }
    /**
     * 链表:
     */
    
    public class MyLinkList {
    
        int size;  // 链表大小
    
        Node head;  // 头链表
    
        // 初始化链表
        public MyLinkList() {
            this.size = 0;
            this.head = null;
        }
    
        // 链表添加 从末尾添加
        public boolean add(int num){
            Node newNode = new Node(num);
            if(head == null){
                head = newNode;
                size++;
                return true;
            }
            // 遍历链表 , 将新元素插入链表尾部
            Node temp = head;
            while(temp.next != null){
                temp = temp.next;
            }
            temp.next = newNode;
            size++;
            return true;
        }
    
        // 链表添加 从表头添加
        public boolean addFromHead(int num){
            Node temp = new Node(num);
            if(head == null){
                head = temp;
            }
            temp.next = head;
            head = temp;
            size++;
            return true;
        }
    
        // 遍历打印链表
        public void printLinkList(){
            if(head == null){
                System.out.println("null");
            }else {
                Node temp = head;
                while(temp != null){
                    System.out.print(temp.num+"  ");
                    temp = temp.next;
                }
                System.out.println();
            }
    
        }
    
        // 删除链表节点 指定位置
        public boolean removeNode(int index){
            if(head == null){
                return false;
            }
            if(index < 1 || index > size){
                return false;
            }
            if(index == 1){
                head = head.next;
                size--;
                return true;
            }
    
            // 找到该节点的前节点
            Node temp = head;
            Node nextTemp = head.next;  // nextTemp最终为index出节点   temp最终为index节点的前节点
            for(int i=1; i<index-1; i++){
                temp = temp.next;
                nextTemp = nextTemp.next;
            }
            temp.next = nextTemp.next;
            size--;
            return true;
        }
    
    
        // 删除链表节点,指定节点数值 可能含多个
        public boolean removeNodeByNum(int num){
            // 如果从表头开始删除元素,遍历删除直到表头不是要删除的元素
            while(head != null){
                if(head.num == num){
                    head = head.next;
                    size--;
                }else {
                    break;
                }
            }
            // 判断链表是否为空
            if(head == null){
                return false;
            }
    
            // 遍历链表 表头不是要删除的元素,此时以nextTemp为基准
            Node temp = head;
            Node nextTemp = head.next;
            while(nextTemp != null){
    
                if(nextTemp.num == num){
                    temp.next = nextTemp.next;
                    nextTemp = nextTemp.next;
                    size--;
                    continue;
                }
                temp = temp.next;
                nextTemp = nextTemp.next;
            }
            return true;
        }
    
        // 链表反转
        public void reserve(){
            if(head == null || head.next == null){
                return;
            }
            Node pre = null;  // 前结点
            Node curNode = head;  // 当前节点
            Node nextNode = null;  // 下个节点
    
            while(curNode != null){
                nextNode = curNode.next;
                curNode.next = pre;
                pre = curNode;
                curNode = nextNode;
            }
            head = pre;  // 此时curNode已经为null了,最后的pre才是反转后链表的头节点
        }
    
        // 去除重复元素
        public void distinctLink(){
            if(head == null || head.next == null){
                return ;
            }
            Node temp = head;
            Node nextNode = head.next;
            Map map = new HashMap(16);
            map.put(temp.num,1);  // 将头节点放入map中
            while(nextNode != null){
                if(!map.containsKey(nextNode.num)){
                    map.put(nextNode.num,1);
                }else{
                    // 如果包含了,删除该节点
                    temp.next = nextNode.next;
                    size--;
                    nextNode = nextNode.next;
                    continue;
                }
                temp = temp.next;
                nextNode = nextNode.next;
            }
        }
    
        // 去除重复元素2
        public void distinctLink2(){
            Node curNode = head;
            Node preNode = null;
            Map map = new HashMap(8);
            while(curNode != null){
                if(map.containsKey(curNode.num)){
                    // 如果包含
                    preNode.next = curNode.next;
                    size--;
                }else {
                    // 如果不包含
                    map.put(curNode.num,1);
                    preNode = curNode;
                }
                curNode = curNode.next;
            }
        }
    
    
        // 节点排序 选择排序
        public void sortLinkList(){
    
            if(head ==null || head.next == null){
                return;
            }
            Node curNode = head;
            while(curNode != null){
                Node nextNode = curNode.next;
                while(nextNode != null){
                    if(curNode.num > nextNode.num){
                        int temp = curNode.num;
                        curNode.num = nextNode.num;
                        nextNode.num = temp;
                    }
                    nextNode = nextNode.next;
                }
                curNode = curNode.next;
            }
    
        }
    
        // 返回倒数第k个结点.  连个指针一个先走k-1步, 第二个指针开始走,当第一个到达尾节点时,第二个刚好到达倒数k个位置
        public Node findReverNode(int k){
    
            if(k < 0 || k > size){
                return null;
            }
            Node firstNode = head;  // 第一个指针
            Node secondNode = head;  // 第二个指针
            // 第二个指针先走k-1步
            for(int i = 0 ; i < k-1 ; i++){
                secondNode = secondNode.next;
            }
            while(secondNode.next != null){
                // 第一个指针开始
                firstNode = firstNode.next;
                secondNode = secondNode.next;
            }
            return firstNode;
        }
    
        // 链表中间节点  快慢指针
        public Node getMidNode(){
            Node quickNode = head;
            Node slowNode = head;
            while(quickNode.next != null && quickNode.next.next != null){
                quickNode = quickNode.next.next;
                slowNode = slowNode.next;
            }
            return slowNode;
        }
    
    
        // 链表中环的检测
        public boolean isCross(){
            Node quickNode = head;
            Node slowNode = head;
            while(quickNode.next != null && quickNode.next.next != null){
                quickNode = quickNode.next.next;
                slowNode = slowNode.next;
                if(quickNode == slowNode){
                    return true;
                }
            }
            return false;
        }
    
        // 维护有序链表
        public void addOrder(int num){
            Node temp = new Node(num);
            if(head == null){
                head = temp;
                size++;
                return ;
            }
            if(num < head.num){
                temp.next = head;
                head = temp;
                size++;
                return;
            }
    
            Node curNode = head;
            Node preNode = null;
            while(curNode.next != null){
                preNode = curNode;
                curNode = curNode.next;
                if(num < curNode.num){
                    preNode.next = temp;
                    temp.next = curNode;
                    size++;
                    return;
                }
            }
            curNode.next = temp;
            size++;
        }
    
    
        // 两个有序的链表合并
        public MyLinkList mergeLinkList(MyLinkList list1,MyLinkList list2){
            Node temp = list2.head;
            while(temp != null){
                list1.addOrder(temp.num);
                temp = temp.next;
            }
    
            return list1;
        }
    
        // 删除尾节点
        public void removeEndNode(){
            if(head == null){
                return;
            }
            if(head.next == null){
                head = null;
                size--;
                return;
            }
            Node curNode = head;
            Node nextNode = head.next;
            while(nextNode.next != null){
                nextNode = nextNode.next;
                curNode = curNode.next;
            }
            curNode.next = null;
            size--;
        }
    
    
    }
    

     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值