初识Java语言——顺序表和链表(基础知识2——查找,插入等算法)(后面又惊喜)

初识Java语言——顺序表和链表(基础知识2——查找,插入等算法)

一、顺序表
实现顺序表代码

import java.util.Arrays;
class MyArrayList{
    
    
    private int useSize;
    private int[]elem;
    //构造方法public MyArrayList(){
    
    
        this.elem=new int[6];
    }
    //打印顺序表public void display(){
    
    
        if(this.useSize==0){
    
    
            System.out.println("null");
            return;
        }
        for(int i=0;i<this.useSize;++i){
    
    
            System.out.print(this.elem[i]+" ");
        }
        System.out.println();
    }
    //在顺序表中插入元素public void insert(int pos,int key){
    
    
        if(pos<0||pos>this.useSize){
    
    
            System.out.println("格式不合法");
            return;
        }
        if(this.useSize==this.elem.length){
    
    
            System.out.println("顺序表已满,扩容为两倍!");
            this.elem=Arrays.copyOf(this.elem,2*(this.elem.length));
        }
        for(int i=this.useSize-1;i>=pos;--i){
    
    
            this.elem[i+1]=this.elem[i];
        }
        this.elem[pos]=key;
        this.useSize++;
    }
    //尾插public void add(int key){
    
    
        if(this.useSize==this.elem.length){
    
    
            System.out.println("顺序表已满,扩容为两倍!");
            this.elem=Arrays.copyOf(this.elem,2*(this.elem.length));
        }
        this.elem[this.useSize]=key;
        this.useSize++;
    }
    //判定是否包含某个元素public boolean contains(int key){
    
    
        if(this.useSize>0){
    
    
            for(int i=0;i<this.useSize;++i){
    
    
                if(this.elem[i]==key){
    
    
                    return true;
                }
            }
        }
        return false;
    }
    //查找某个元素对应位置public int search(int key){
    
    
        if(this.useSize>0){
    
    
            for(int i=0;i<this.useSize;++i){
    
    
                if(this.elem[i]==key){
    
    
                    return i;
                }
            }
        }
        return -1;
    }
    //获取pos位置的元素public int getPos(int pos){
    
    
        if(pos>=0&&pos<this.useSize){
    
    
            return this.elem[pos];
        }
        return -1;
    }
    //给pos位置设置为valuepublic void setPos(int pos,int value){
    
    
        if(pos>=0&&pos<this.useSize){
    
    
            this.elem[pos]=value;
        }else{
    
    
            System.out.println("pos不合法");
        }
    }
    //删除第一次出现的关键字keypublic void remove(int key){
    
    
        if(this.useSize>0){
    
    
            if(search(key)!=-1){
    
    
                for(int i=search(key);i<this.useSize-1;++i){
    
    
                    this.elem[i]=this.elem[i+1];
                }
                this.useSize--;
                System.out.println("已删除!");
            }else{
    
    
                System.out.println("没有找到要删除的关键字!");
            }
        }else{
    
    
            System.out.println("顺序表为空,不需要删除!");
        }
    }
    //获取顺序表长度public int size(){
    
    
        return this.useSize;
    }
    //清空顺序表public void clear(){
    
    
        this.useSize=0;
    }
}
public class Main {
    
    
    public static void main(String[] args) {
    
    
    MyArrayList num=new MyArrayList();
    num.insert(0,8);
    num.add(9);
    num.insert(1,18);
    num.display();
    num.remove(8);
    num.display();
    num.add(99);
    num.display();
        System.out.println(num.search(99));
        System.out.println(num.contains(8));
        System.out.println(num.getPos(4));
        num.clear();
        num.display();
    }
}

运行结果如下:
在这里插入图片描述
二、单向链表
1.删除链表重复节点
思路:创建一个傀儡节点,比较当前节点和下一个节点的val是否相同,不相同就往傀儡节点上挂,相同就一直往后遍历,直到找到不相同的,或者链表遍历完,最终返回傀儡节点next。就相当于一个带表头的单链表。

public class Solution {
    
    
    public ListNode deleteDuplication(ListNode pHead)
    {
    
    
   if(pHead==null){
    
    
        return null;
    }else{
    
    
    ListNode newHead=new ListNode(-1);
    ListNode tmp=newHead;
    ListNode cur=pHead;
    while(cur!=null){
    
    
     if(cur.next!=null&&cur.val==cur.next.val){
    
    
         while(cur.next!=null&&cur.val==cur.next.val){
    
    
             cur=cur.next;
         }
         cur=cur.next;
     }else{
    
    
         tmp.next=cur;
         cur=cur.next;
         tmp=tmp.next;
     }
    }
    if(newHead.next==null){
    
    
        return null;
    }
    tmp.next=null;
    return newHead.next;
 }
    }
}

2.编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前
思路:创建4个引用,前两个分别代表小于x的单项链表的头尾,后两个代表大于等于x的单向链表的头尾,然后比较head的val和x的大小关系,在相应的位置尾插就行了,注意head后移。还有让最后一个节点的next变为null

public class Partition {
    
    
    public ListNode partition(ListNode pHead, int x) {
    
    
        ListNode Ls=null;
        ListNode Le=null;
        ListNode Hs=null;
        ListNode He=null;
        if(pHead==null){
    
    
            return null;
        }else{
    
    
            ListNode cur=pHead;
            while(cur!=null){
    
    
                if(cur.val<x){
    
    
                    if(Ls==null){
    
    
                        Le=Ls=cur;
                    }else{
    
    
                        Le.next=cur;
                        Le=Le.next;
                    }
                }else{
    
    
                    if(Hs==null){
    
    
                        Hs=He=cur;
                    }else{
    
    
                        He.next=cur;
                        He=He.next;
                    }
                }
                cur=cur.next;
            }
            if(Ls==null){
    
    
                return Hs;
            }else{
    
    
                if(He!=null){
    
    
                He.next=null;
                }
                Le.next=Hs;
                return Ls;
            }
        }
    }
}

3.合并两个有序链表
思路:创建一个傀儡节点,让两个链表的head.val进行比较,小的就往傀儡节点上插,并将对应的头引用后移,直到其中链表有一个或都遍历完(head为null)就停,再将没遍历完的尾插到傀儡节点所指向链表上。

public class Partition {
    
    
    public ListNode partition(ListNode pHead, int x) {
    
    
        ListNode Ls=null;
        ListNode Le=null;
        ListNode Hs=null;
        ListNode He=null;
        if(pHead==null){
    
    
            return null;
        }else{
    
    
            ListNode cur=pHead;
            while(cur!=null){
    
    
                if(cur.val<x){
    
    
                    if(Ls==null){
    
    
                        Le=Ls=cur;
                    }else{
    
    
                        Le.next=cur;
                        Le=Le.next;
                    }
                }else{
    
    
                    if(Hs==null){
    
    
                        Hs=He=cur;
                    }else{
    
    
                        He.next=cur;
                        He=He.next;
                    }
                }
                cur=cur.next;
            }
            if(Ls==null){
    
    
                return Hs;
            }else{
    
    
                if(He!=null){
    
    
                He.next=null;
                }
                Le.next=Hs;
                return Ls;
            }
        }
    }
}

4.输入一个链表,输出该链表中倒数第k个结点
思路:快慢指针法。定义两个引用fast和slow都指向head,fast先走k-1步,然后fast和slow同时走,当fast.next为null时,slow所指向的就是倒数第k个节点。注意,可能面临k的值大于节点个数的问题,所以要在fast走k-1步时在内部加一条判断,当fast.next为null时直接return null结束。

public class Solution {
    
    
    public ListNode FindKthToTail(ListNode head,int k) {
    
    
     if(head==null||k<=0){
    
    
         return null;
     }
         ListNode fast=head;
         ListNode slow=head;
         while(k>1){
    
    
             if(fast.next==null){
    
    
                 return null;
             }
             fast=fast.next;
             k--;
         }
         while(fast.next!=null){
    
    
             fast=fast.next;
             slow=slow.next;
         }
         return slow;
    }
} 

5.返回链表的中间结点
思路:还是快慢指针,fast走两步,slow走一步,直到fast的next为null时,slow所指即为中间节点。

public boolean chkPalindrome() {
    
    
        Node head=this.head;
        Node slow=null;
        Node fast=this.head;
        Node low=this.head;
        while(fast!=null&&fast.next!=null){
    
    
        fast=fast.next.next;
        low=low.next;
        }
        slow=low;
        Node cur=slow.next;
        Node end=cur.next;
         while(end!=null){
    
    
        cur.next=slow;
        slow=cur;
        cur=end;
        end=end.next;
}
        cur.next=slow;
        slow=cur;
        while(head != slow) {
    
    
        if(head.val!=slow.val){
    
    
        return false;
}else{
    
    
head=head.next;
slow=slow.next;
}
        }
return true;
    }

6.反转一个单链表
思路:定义三个引用,一个指向当前节点的前一个节点,没有就指向null,一个指向当前节点,最后一个指向当前节点的下一个节点,我们只需要让当前节点的next指向第一个引用所指向的节点,第一个引用后移指向第二个引用所指向的节点,第二个引用后移指向最后一个引用所指向的节点,最后一个引用后移,重复上述操作,直到最后一个引用指向空。

class Solution {
    
    
    public ListNode reverseList(ListNode head) {
    
    
     if(head==null){
    
    
     return null;
     }else{
    
    
         ListNode cur=head;
         ListNode per=null;
         ListNode nextNode=cur.next;
         while(nextNode!=null){
    
    
          cur.next=per;
          per=cur;
          cur=nextNode;
          nextNode=nextNode.next;
         }
         cur.next=per;//注意,nextNode为null时,cur才刚指上最后一个节点,还没完成反转,所以要加这条语句
         return cur;
     }
    }
}

7.删除链表中等于给定值 val 的所有节点
思路:一个一个比较,头节点单独处理。

class Solution {
    
    
    public ListNode removeElements(ListNode head, int val) {
    
    
    if(head==null){
    
    
    return null;
    }else{
    
    
    ListNode cur=head;
    ListNode per=cur.next;
    while(per!=null){
    
    
    if(per.val==val){
    
    
    cur.next=per.next;
    } else{
    
    
      cur=cur.next;  
    }
    per=per.next;
    }
    if(head.val==val){
    
    
    head=head.next;
    }
    return head;
    }
    }
}

三、加餐:双向链表
和单向链表类似,只不过一个节点内部有三部分,val、前驱引用(prev)、后继引用(next)。
在这里插入图片描述
创建一个双向链表:

class ListNode{
    
    
    private int val;
    private ListNode next;
    private ListNode prev;
    public ListNode(){
    
    

    }
    public ListNode(int val){
    
    
        this.val=val;
    }
    public int getVal(){
    
    
        return this.val;
    }
    public ListNode getNext(){
    
    
        return this.next;
    }
    public ListNode getPrev(){
    
    
        return this.prev;
    }
    public void setVal(int val){
    
    
        this.val=val;
    }
    public void setNext(ListNode next){
    
    
        this.next=next;
    }
    public void setPrev(ListNode prev){
    
    
        this.prev=prev;
    }
}
public class DoubleLinkList {
    
    
    ListNode head;
    ListNode last;
    //头插public void addHead(int val){
    
    
    ListNode cur=new ListNode(val);
    if(this.head==null){
    
    
    this.head=cur;
    this.last=cur;
    }else{
    
    
     cur.setNext(this.head);
     this.head.setPrev(cur);
     this.head=cur;
    }
    }
    //尾插public void addLast(int val){
    
    
      ListNode cur=new ListNode(val);
    if(this.head==null){
    
    
     this.head=cur;
     this.last=cur;
    } else{
    
    
     this.last.setNext(cur);
     cur.setPrev(this.last);
     this.last=cur;
    }
    }
    //打印public void display(){
    
    
        ListNode cur=this.head;
      while(cur!=null){
    
    
          System.out.print(cur.getVal()+"->");
          cur=cur.getNext();
      }
        System.out.println();
    }
}
//Main
public class Main {
    
    
    public static void main(String[] args) {
    
    
        DoubleLinkList head=new DoubleLinkList();
        head.addHead(8);
        head.addHead(8);
        head.addHead(8);
        head.addLast(6);
        head.addLast(6);
        head.addLast(6);
        head.display();
    }
}

运行结果如下:
在这里插入图片描述
不知不觉已经到学完链表了,一起加油吧!

猜你喜欢

转载自blog.csdn.net/qq_45841205/article/details/112403644
今日推荐