链表

单链表

介绍:

  1)有序的列表。

  2)以节点的方式存储,是链式存储。

  3)每个节点包含data域,next域:指向下一个节点。

  4)链表的各个节点不一定是连续存储。

  5)分为带头节点的链表没有头节点的链表

使用:

  1.求单链表中有效节点个数

  答:遍历链表。

  2.查找单链表中倒数第k个节点

  答:先遍历链表,得出总长,再遍历找出倒数第k个元素

  3.单链表的反转

  答:1)新建一个单链表,遍历原单链表,每一个元素放到新单链表的头。

    2)使用stack,利用stack先进后出的特性。

缺点:

  1)查找只能是一个方向。

  2)不能自我删除,需要靠辅助节点。

双链表

介绍:

  1)遍历方式与单链表相同,可以向前,也可以向后

  2)添加(默认天加到双向链表的最后)

    i.先找到双向链表的最后节点

    ii.temp.next = newNode

    iii.newNode.pre = temp

  3)修改,与单链表思路相同

  4)删除,能够自我删除

    i.temp.pre.next = temp.next

    ii.temp.next.pre = temp.pre

单向环形链表

场景:Josephu(约瑟夫、约瑟夫环)问题

    问题:设编号为 1,2,… n 的 n 个人围坐一圈,约定编号为 k(1<=k<=n)的人从 1 开始报数,数 到 m 的那个人出列,它的下一位又从 1 开始报数,数到 m 的那个人又出列,依次类推,直到所有人出列为止,由 此产生一个出队编号的序列。

代码如下:

链表
public class Josephu { 
    public static void main(String[] args) {      
        CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();  
        circleSingleLinkedList.addBoy(5);  
        circleSingleLinkedList.shwBoy();  
        circleSingleLinkedList.countBoy(1, 3, 5);  
    }
}
class CircleSingleLinkedList 
{ 
    private Boy first = null;
    
    public void addBoy(int nums) {      
        if (nums < 1) {      
            System.out.println("nums的值不正确");  
            return;  
        }  
        Boy curBoy = null;  
        for (int i = 1; i <= nums; i ++) {      
            Boy boy = new Boy(i);     
            if (i == 1) {      
                first = boy;     
                first.setNext(first);     
                curBoy = first;  
            } else {      
                curBoy.setNext(boy);     
                boy.setNext(first);     
                curBoy = boy;  
            }  
        }  
    }
    
    public void shwBoy() {      
        if (first == null) {      
            System.out.println("没有数据");     
            return;  
        }  
        Boy curBoy = first;     
        while (true) {      
            System.out.printf("小孩的编号 %d\n", curBoy.getNo());     
            if (curBoy.getNext() == first) {      
                break;  
            }  
            curBoy = curBoy.getNext();  
        }  
    }
    
    public void countBoy(int startNo, int countNum, int nums) {      
        if (first == null || startNo < 1 || startNo > nums) {      
            System.out.println("参数输入有误,请重新输入");     
            return;  
        }  
        Boy helper = first;
        
        while (true) {      
            if (helper.getNext() == first) {      
                break;  
            }  
            helper = helper.getNext();  
        }
        
        for (int j = 0; j < startNo - 1; j ++) {      
            first = first.getNext();     
            helper = helper.getNext();  
        }
        
        while (true) {      
            if (helper == first) {      
                break;  
            }  
            for (int j = 0; j < countNum - 1; j ++) {      
                first = first.getNext();     
                helper = helper.getNext();  
            }  
            System.out.printf("%d\n", first.getNo());     
            first = first.getNext();     
            helper.setNext(first);  
        }  
        System.out.printf("11%d\n", first.getNo());
    
    }
}
class Boy { 
    private int no;
    private Boy next;
    public Boy(int no) {      
        this.no = no;  
    }  
    public int getNo() {      
        return no;  
    }  
    public void setNo(int no) {      
        this.no = no;  
    }  
    public Boy getNext() {      
        return next;  
    }  
    public void setNext(Boy next) {      
        this.next = next;  
    }
}
View Code

思路:构建一个单项环形链表。first是头,rear是尾。从第k个报数,first和rear就要先移动k-1个位置。数到m的出列,while循环,每次移动m-1个位置,first就是要出列的,再指向下一位,first = first.next  rear.next = first

  

上一篇:273. Integer to English Words


下一篇:yii学习的第三天(两种验证方式)