CF459E Pashmak and Graph
阿新 • • 發佈:2020-12-02
連結串列
連結串列是一種線性結構
上述分別為連結串列的邏輯結構和記憶體結構(實際在記憶體中儲存順序是不連續的)
連結串列的的每一個節點有兩部分組成,第一部分儲存相應的資料,另一部分儲存下一個節點的地址,最後一個節點的next指向null
連結串列的特點是增刪快,查詢慢
雙向連結串列
public class SingleNode { //雙向連結串列 //相對於單向連結串列來講有兩個方向可以操作連結串列 //兩個方向定義頭結點和尾節點 class DoubkeLikendList{ Node head = new Node(0,null); Node tail= new Node(0,null); public void add(Node node){ Node temp = head; while(true){ if(temp.next==null){ temp.next=node; //與單向連結串列相同,將最後一個節點的next指向新加入的節點 node.pre=temp //將新加入的節點的上一個指向此時的temp(新加入的上一個)tail=node; break; } temp=temp.next; } } public void change(int no){ //按照編號修改姓名 //與單向連結串列類似 Node temp = head; while(true){ if(temp.no==no){ temp.name="新名字"; break; } if(temp.next==null){ System.out.println("沒有要找到刪除的節點"); break; } temp=temp.next; } } //按照指定編號刪除節點 //相對於單向連結串列來講,可以實現自我刪除,而單向連結串列需要一個輔助節點 public void delete(int no){ Node temp = head; while(true){ if(temp.no==no){ if(temp.pre==null){ temp.next.pre=temp.pre; //防止空指標異常 }else if(temp.next==null){ temp.pre.next=temp.next; //防止空指標異常 }else{ temp.next.pre=temp.pre; //將該節點的下一個的前一個指向給節點的前一個 temp.pre.next=temp.next; //將該節點的前一個的下一個指向給節點的下一個 //經過上面兩步以後該節點就成為一個“垃圾”,有JVM自動回收 } break; } if(temp.next==null){ System.out.println("沒有要找到刪除的節點"); break; } temp=temp.next; } } public void allNode(){ //利用尾節點遍歷 Node temp = tail; while(true){ if(temp.next==null){ System.out.println(temp); break; } System.out.println(temp); temp=temp.next; } } } class Node{ public int no; public String name; public Node next;//指向該節點的下一個節點 public Node pre;//指向該節點的前一個節點 public Node(int no , String name) { this.no = no; this.name=name; } @Override public String toString() { return "Node{" + "no=" + no + ", name='" + name ; } } }
迴圈連結串列
、、最後一個節點指向第一個節點構成一個環形
public class CircleNode { //最後一個節點的next指向第一個節點 /* 約瑟夫問題: 約瑟夫問題是個有名的問題:N個人圍成一圈,從第一個開始報數,第M個將出隊,最後剩下一個。 */ class MethodYuesefu{ Node2 first; public void addN(int N){ //按輸入的N,建立指定大小的初始連結串列 if(N<1){ System.out.println("輸入的資料不合法"); return; } Node2 assman = null;//輔助節點 for (int i = 1; i < N+1; i++) { Node2 man = new Node2(i); if(i==1){ first=man; first.setNext(first); assman = first; //只有一個數據的連結串列,自我構成迴圈 }else{ assman.setNext(man); man.setNext(first); //將新加入的節點的next指向第一個構成迴圈(新加入的一定是最後一個) assman=man; } } } public void allMan(){ Node2 temp = first; if(first==null){ System.out.println("連結串列為空~~"); return; } while(true){ System.out.println(temp); if(temp.getNext()==first){ //遍歷結束條件是重新找到了第一個節點 break; } temp=temp.getNext(); } } /** * * @param startNo 從第幾個編號開始數 * @param num 每一次數幾個數 * @param N 總人數 */ public void countMan(int startNo,int num,int N){ if(first==null|| startNo<1||startNo>N){ System.out.println("輸入的資料不符合要求"); return; } Node2 helper = first;//用來指向first的前一個節點 while(true){ //找到first的前一個元素,並將其賦值給helper if (helper.getNext()==first){ break; } helper=helper.getNext(); } for (int i = 0; i < startNo-1; i++) { //將first移到開始的位置 first=first.getNext(); helper = helper.getNext(); } while(true){ if(helper==first){ //只剩下一個數據 System.out.println("剩下的編號"); break; } for (int i = 0; i <num-1; i++) { //數數 first=first.getNext(); helper = helper.getNext(); } System.out.println("出圈:"+first.getNo()); first=first.getNext(); helper.setNext(first); //將數到的節點刪除,直接將helpter指向新first,那麼原新的first就訪問不到了成為了垃圾 } } } class Node2{ private int no; private Node2 next; public Node2(int no) { this.no = no; } @Override public String toString() { return "Node2{" + "no=" + no + '}'; } public int getNo() { return no; } public void setNo(int no) { this.no = no; } public Node2 getNext() { return next; } public void setNext(Node2 next) { this.next = next; } } }