链表
1.单链表
(1)单链表的增、删、改、查、查找倒数第K个节点、链表反转
1 package LianBiao; 2 3 import java.util.Stack; 4 5 /* 6 * 单链表:头节点不存数据,只存下一节点地址 7 * 编号唯一 8 */ 9 public class LinkedListDemo1 { 10 public static void main(String[] args){ 11 MyLinkedList1 t=new MyLinkedList1(); 12 13 t.addNodeByNo(1, "宋江", "及时雨"); 14 t.addNodeByNo(3, "吴用", "智多星"); 15 t.addNodeByNo(2, "卢俊义", "玉麒麟"); 16 t.addNodeByNo(4, "林冲", "豹子头"); 17 t.addNodeByNo(5, "武松", "行者"); 18 t.addNodeByNo(6, "鲁智深", "花和尚"); 19 t.show(); 20 System.out.println("-------------"); 21 //System.out.println("链表长度:"+t.getListLength()); 22 //System.out.println("-------------"); 23 //t.getLastNode(8); 24 25 //t.reverseList(); 26 t.reverseList1(); 27 28 //t.findNodeByNo1(4); 29 30 //t.findNodeByName1("宋江"); 31 //System.out.println("-----------------"); 32 //t.deleteNode1(5); 33 //t.show(); 34 35 } 36 37 } 38 39 class Node1{ 40 41 int no; 42 String name; 43 String nickName; 44 Node1 next; 45 public Node1(int no, String name, String nickName, Node1 next) { 46 this.no = no; 47 this.name = name; 48 this.nickName = nickName; 49 this.next = next; 50 } 51 @Override 52 public String toString() { 53 return "座次: " + no + ", 姓名: " + name + ", 绰号: " + nickName; 54 } 55 @Override 56 public int hashCode() { 57 final int prime = 31; 58 int result = 1; 59 result = prime * result + ((name == null) ? 0 : name.hashCode()); 60 result = prime * result + ((next == null) ? 0 : next.hashCode()); 61 result = prime * result + ((nickName == null) ? 0 : nickName.hashCode()); 62 result = prime * result + no; 63 return result; 64 } 65 @Override 66 public boolean equals(Object obj) { 67 if (this == obj) 68 return true; 69 if (obj == null) 70 return false; 71 if (getClass() != obj.getClass()) 72 return false; 73 Node1 other = (Node1) obj; 74 if (name == null) { 75 if (other.name != null) 76 return false; 77 } else if (!name.equals(other.name)) 78 return false; 79 if (next == null) { 80 if (other.next != null) 81 return false; 82 } else if (!next.equals(other.next)) 83 return false; 84 if (nickName == null) { 85 if (other.nickName != null) 86 return false; 87 } else if (!nickName.equals(other.nickName)) 88 return false; 89 if (no != other.no) 90 return false; 91 return true; 92 } 93 94 95 96 } 97 98 class MyLinkedList1{ 99 100 Node1 head=new Node1(0,"","",null); 101 102 103 104 //添加节点 105 public void addNode(int no, String name, String nickName){ 106 Node1 temp=head; 107 //遍历整个链表,寻找尾节点 108 while(true){ 109 if(temp.next==null){ 110 break; 111 }else{ 112 temp=temp.next; 113 } 114 } 115 116 temp.next=new Node1(no,name,nickName,null); 117 } 118 119 120 121 122 //添加节点,使得添加进去的数据按照编号由小到大排序,这样取出来时直接就是排好的数据,不需要在遍历功能的代码里再想办法实现排序,有点类似set。 123 //同时保证编号的唯一性 124 public void addNodeByNo(int no, String name, String nickName){ 125 Node1 temp=head; 126 boolean flag=false; 127 while(true){ 128 if(temp.next==null){ 129 break; 130 }else{ 131 if(temp.next.no==no){ 132 flag=true; 133 break; 134 }else{ 135 if(temp.next.no>no){ 136 break; 137 }else{ 138 temp=temp.next; 139 } 140 } 141 } 142 } 143 if(flag==true){ 144 System.out.println("编号重复!!!"); 145 }else{ 146 temp.next=new Node1(no,name,nickName,temp.next); 147 } 148 } 149 150 151 152 153 //遍历整个链表:因为头节点只存下一节点的地址而不存数据,所以从头节点的下一个节点开始遍历 154 public void show(){ 155 if(head.next==null){ 156 System.out.println("链表为空!!!"); 157 }else{ 158 Node1 temp=head.next;//这里的指针指的是head.next 159 while(true){ 160 if(temp==null){ 161 break; 162 }else{ 163 System.out.println(temp); 164 temp=temp.next; 165 } 166 } 167 } 168 } 169 170 171 172 173 174 //删除节点(根据编号删除)---成功实现,代码有点复杂,需要优化代码 175 public void deleteNode(int no){ 176 if(head.next==null){ 177 System.out.println("链表为空!!!"); 178 }else{ 179 Node1 temp=head;//这里的指针指的是head 180 while(true){ 181 if(temp.next==null){ 182 if(temp.no!=no){ 183 System.out.println("无此人!!!"); 184 break; 185 }else{ 186 temp=null; 187 break; 188 } 189 }else{ 190 if(temp.next.no==no){ 191 temp.next=temp.next.next; 192 break; 193 }else{ 194 temp=temp.next; 195 } 196 } 197 } 198 } 199 } 200 201 202 203 204 //优化:删除节点功能(根据编号删除) 205 206 public void deleteNode1(int no){ 207 if(head.next==null){ 208 System.out.println("链表为空!!!"); 209 }else{ 210 boolean flag=false;; 211 Node1 temp=head;//这里的指针指的是head 212 while(true){ 213 if(temp.next==null){ 214 break; 215 }else{ 216 if(temp.next.no==no){ 217 //temp.next=temp.next.next; 218 flag=true; 219 break; 220 }else{ 221 temp=temp.next; 222 } 223 } 224 } 225 if(flag){ 226 temp.next=temp.next.next; 227 }else{ 228 System.out.println("无此人!!!"); 229 } 230 } 231 } 232 233 234 235 236 //修改节点数据(根据编号修改)---成功实现,代码有点复杂,需要优化代码 237 public void modifyNode(int no,String name,String nickName){ 238 if(head.next==null){ 239 System.out.println("链表为空!!!"); 240 }else{ 241 Node1 temp=head.next;//这里的指针指的是head.next 242 while(true){ 243 if(temp.next==null){ 244 if(temp.no!=no){ 245 System.out.println("无此人!!!"); 246 break; 247 }else{ 248 temp.name=name; 249 temp.nickName=nickName; 250 break; 251 } 252 }else{ 253 if(temp.no==no){ 254 temp.name=name; 255 temp.nickName=nickName; 256 break; 257 }else{ 258 temp=temp.next; 259 } 260 } 261 } 262 } 263 } 264 265 266 //优化:修改节点数据(根据编号修改) 267 public void modifyNode1(int no,String name,String nickName){ 268 if(head.next==null){ 269 System.out.println("链表为空!!!"); 270 }else{ 271 boolean flag;//设置标志,用来表示是否找到相应数据 272 Node1 temp=head.next;//这里的指针指的是head.next 273 while(true){ 274 if(temp==null){ 275 flag=false; 276 }else{ 277 if(temp.no==no){ 278 flag=true; 279 break; 280 }else{ 281 temp=temp.next; 282 } 283 } 284 } 285 286 if(flag==true){ 287 temp.name=name; 288 temp.nickName=nickName; 289 }else{ 290 System.out.println("无此人!!!"); 291 } 292 } 293 } 294 295 296 297 298 //查询节点(根据编号:编号拥有唯一性)---成功实现,代码有点复杂,需要优化代码 299 public void findNodeByNo(int no){ 300 if(head.next==null){ 301 System.out.println("链表为空!!!"); 302 }else{ 303 Node1 temp=head.next; 304 while(true){ 305 if(temp.next==null){ 306 if(temp.no==no){ 307 System.out.println(temp); 308 break; 309 310 }else{ 311 System.out.println("查无此人"); 312 break; 313 } 314 }else{ 315 if(temp.no==no){ 316 System.out.println(temp); 317 }else{ 318 temp=temp.next; 319 } 320 } 321 } 322 323 } 324 325 } 326 327 328 329 330 //优化:查询节点(根据编号:编号拥有唯一性) 331 public void findNodeByNo1(int no){ 332 if(head.next==null){ 333 System.out.println("链表为空!!!"); 334 }else{ 335 Node1 temp=head.next; 336 while(true){ 337 if(temp==null){ 338 System.out.println("查无此人"); 339 break; 340 }else{ 341 if(temp.no==no){ 342 System.out.println(temp); 343 break; 344 }else{ 345 temp=temp.next; 346 } 347 } 348 } 349 350 } 351 352 } 353 354 355 356 357 358 //查询节点(根据姓名,注:姓名不唯一)---成功实现,代码有点复杂,需要优化代码 359 360 public void findNodeByName(String name){ 361 int count=0; 362 if(head.next==null){ 363 System.out.println("链表为空!!!"); 364 }else{ 365 Node1 temp=head.next; 366 while(true){ 367 if(temp.next==null){ 368 if(temp.name.equals(name)){ 369 System.out.println(temp); 370 count++; 371 break; 372 }else{ 373 break; 374 } 375 }else{ 376 if(temp.name.equals(name)){ 377 System.out.println(temp); 378 count++; 379 temp=temp.next; 380 }else{ 381 temp=temp.next; 382 } 383 } 384 } 385 if(count==0){ 386 System.out.println("没有关于"+name+"的信息!!!"); 387 } 388 389 } 390 391 } 392 393 394 395 396 397 //查询节点(根据姓名,注:姓名不唯一) 398 public void findNodeByName1(String name){ 399 if(head.next==null){ 400 System.out.println("链表为空!!!"); 401 }else{ 402 boolean flag=false;//用来标识是否找到相应的数据 403 Node1 temp=head.next; 404 while(true){ 405 if(temp==null){ 406 break; 407 }else{ 408 if(temp.name.equals(name)){ 409 flag=true; 410 System.out.println(temp); 411 temp=temp.next; 412 }else{ 413 temp=temp.next; 414 } 415 } 416 } 417 if(flag==false){ 418 System.out.println("无此人!!!"); 419 } 420 421 } 422 } 423 424 425 426 427 428 429 //查询节点(根据绰号,绰号没有唯一性)---成功实现,代码有点复杂,需要优化代码 430 public void findNodeBynickName(String nickName){ 431 int count=0; 432 if(head.next==null){ 433 System.out.println("链表为空!!!"); 434 }else{ 435 Node1 temp=head.next; 436 while(true){ 437 if(temp.next==null){ 438 if(temp.nickName.equals(nickName)){ 439 System.out.println(temp); 440 count++; 441 break; 442 }else{ 443 break; 444 } 445 }else{ 446 if(temp.nickName.equals(nickName)){ 447 System.out.println(temp); 448 count++; 449 temp=temp.next; 450 }else{ 451 temp=temp.next; 452 } 453 } 454 } 455 456 } 457 if(count==0){ 458 System.out.println("没有关于"+nickName+"的信息!!!"); 459 } 460 461 } 462 463 464 465 //优化:查询节点(根据绰号,绰号拥有唯一性) 466 public void findNodeBynickName1(String nickName){ 467 if(head.next==null){ 468 System.out.println("链表为空!!!"); 469 }else{ 470 boolean flag=false;//用来标识是否找到相应的数据 471 Node1 temp=head.next; 472 while(true){ 473 if(temp==null){ 474 break; 475 }else{ 476 if(temp.nickName.equals(nickName)){ 477 flag=true; 478 System.out.println(temp); 479 temp=temp.next; 480 }else{ 481 temp=temp.next; 482 } 483 } 484 } 485 486 if(flag==false){ 487 System.out.println("无此人!!!"); 488 } 489 490 } 491 492 493 } 494 495 //获取链表中的有效节点个数 496 497 public int getListLength(){ 498 int count=0; 499 if(head.next==null){ 500 System.out.println("链表为空!!!"); 501 return 0; 502 }else{ 503 Node1 temp=head.next; 504 while(true){ 505 if(temp!=null){ 506 count++; 507 temp=temp.next; 508 }else{ 509 break; 510 } 511 } 512 //System.out.println("有效节点个数为:"+count); 513 return count; 514 } 515 } 516 517 518 519 //获取链表中倒数第k个节点 520 public void getLastNode(int index){ 521 int size=getListLength(); 522 if(index<1||index>size){ 523 System.out.println("超出范围"); 524 }else{ 525 Node1 temp=head.next; 526 for(int i=0;i<size-index;i++){ 527 temp=temp.next; 528 } 529 System.out.println("获取倒数第"+index+"节点:"); 530 System.out.println(temp); 531 } 532 533 } 534 535 536 //反转链表(改变原链表的顺序,使其也为反向) 537 public void reverseList(){ 538 MyLinkedList1 reverseList=new MyLinkedList1(); 539 if(head.next==null){ 540 System.out.println("链表为空!!!"); 541 }else{ 542 Node1 temp=head.next; 543 Node1 save; 544 Node1 header=new Node1(0,"","",null); 545 while(true){ 546 if(temp==null){ 547 break; 548 }else{ 549 save=temp.next; 550 /* 551 temp.next=temp; 552 temp=save; 553 */ 554 temp.next=header.next; 555 header.next=temp; 556 temp=save; 557 } 558 } 559 reverseList.head.next=header.next; 560 reverseList.show(); 561 562 } 563 564 565 } 566 567 568 //反转链表(不改变原链表的结构)---使用栈 569 public void reverseList1(){ 570 if(head.next==null){ 571 System.out.println("链表为空!!!"); 572 }else{ 573 //创建一个栈 574 Stack stack=new Stack(); 575 int count=0; 576 Node1 temp=head.next;//这里的指针指的是head.next 577 while(true){ 578 if(temp==null){ 579 break; 580 }else{ 581 stack.add(temp); 582 count++; 583 temp=temp.next; 584 } 585 } 586 for(int i=0;i<count;i++){ 587 System.out.println( stack.pop()); 588 } 589 } 590 } 591 592 593 594 }
(2)链表排序
1 package XianXingBiao; 2 /* 3 * 使用链表: 4 * 未做完,比较大小部分有问题 5 */ 6 import java.util.LinkedList; 7 import java.util.List; 8 9 public class PaiXuTest2 { 10 public static void main(String[] args){ 11 int[] a={1,3,5,7,9}; 12 int[] b={2,6,8,10,12}; 13 NewLinkedList l1=new NewLinkedList(); 14 NewLinkedList l2=new NewLinkedList(); 15 16 for(int i=0;i<a.length;i++){ 17 l1.addNode(a[i]);; 18 } 19 20 for(int j=0;j<a.length;j++){ 21 l2.addNode(b[j]); 22 } 23 l1.showLink(); 24 l2.showLink(); 25 26 /* 27 PaiXuTest2 t=new PaiXuTest2(); 28 t.paiXu1(l1, l2); 29 */ 30 31 32 33 34 35 36 37 38 } 39 40 //排序:未成功,结果里面有错误(一定要注意:若要操作某个节点,应当将指针指在它的前一个节点,和删除节点的道理一样) 41 public void paiXu(NewLinkedList a,NewLinkedList b){ 42 System.out.println("排序如下:"); 43 Node ta=a.head.next; 44 Node tb=b.head.next; 45 Node temp; 46 NewLinkedList c=new NewLinkedList(); 47 temp=c.head; 48 49 while(ta.next!=null&&tb.next!=null){ 50 if(ta.data<tb.data){ 51 temp.next=ta; 52 ta=ta.next; 53 temp=temp.next; 54 }else{ 55 temp.next=tb; 56 tb=tb.next; 57 temp=temp.next; 58 } 59 } 60 61 if(ta.next!=null){ 62 temp.next=ta; 63 } 64 if(tb.next!=null){ 65 temp.next=tb; 66 } 67 c.showLink(); 68 69 70 } 71 72 //排序:成功(一定要注意:若要操作某个节点,应当将指针指在它的前一个节点,和删除节点的道理一样) 73 public void paiXu1(NewLinkedList a,NewLinkedList b){ 74 System.out.println("排序如下:"); 75 Node ta=a.head.next; 76 Node tb=b.head.next; 77 Node temp; 78 NewLinkedList c=new NewLinkedList(); 79 temp=c.head; 80 81 while(ta!=null&&tb!=null){ 82 if(ta.data<tb.data){ 83 temp.next=ta; 84 ta=ta.next; 85 temp=temp.next; 86 }else{ 87 temp.next=tb; 88 tb=tb.next; 89 temp=temp.next; 90 } 91 } 92 93 if(ta!=null){ 94 temp.next=ta; 95 } 96 if(tb!=null){ 97 temp.next=tb; 98 } 99 c.showLink(); 100 101 102 } 103 104 105 //运行结果为空,未查找问题,回头查找问题 106 public void paiXu2(NewLinkedList a,NewLinkedList b){ 107 System.out.println("排序如下:"); 108 Node ta=a.head.next; 109 Node tb=b.head.next; 110 Node temp; 111 NewLinkedList c=new NewLinkedList(); 112 temp=c.head.next; 113 //c.head.next=temp; 114 while(ta!=null&&tb!=null){ 115 if(ta.data<tb.data){ 116 System.out.println("--------------------"); 117 temp=ta; 118 System.out.println(c.head.next); 119 System.out.println("temp=ta="+temp); 120 System.out.println("temp.next=ta.next"+temp.next); 121 ta=ta.next; 122 //System.out.println("ta-->"+ta); 123 temp=temp.next; 124 System.out.println("temp:"+temp); 125 System.out.println("--------------------"); 126 }else{ 127 System.out.println("**********"); 128 temp=tb; 129 System.out.println("temp=tb="+temp); 130 System.out.println("temp.next=tb.next"+temp.next); 131 //System.out.println("tb"+tb); 132 tb=tb.next; 133 //System.out.println("tb.next"+tb.next); 134 temp=temp.next; 135 System.out.println("temp:"+temp); 136 System.out.println("**********"); 137 138 } 139 } 140 141 if(ta!=null){ 142 temp=ta; 143 System.out.println("--------"+temp); 144 } 145 if(tb!=null){ 146 temp=tb; 147 System.out.println("*******"+temp); 148 } 149 System.out.println(c.head.next); 150 c.showLink(); 151 152 153 } 154 155 156 157 158 } 159 160 class Node{ 161 int data; 162 Node next; 163 164 public Node(){ 165 166 } 167 168 public Node(int data,Node next){ 169 this.data=data; 170 this.next=next; 171 } 172 173 @Override 174 public String toString() { 175 return " " + data ; 176 } 177 178 179 180 181 } 182 183 class NewLinkedList{ 184 185 Node head=new Node(-1,null); 186 187 //增加节点 188 public void addNode(int data){ 189 190 Node temp=head; 191 while(true){ 192 if(temp.next==null){ 193 temp.next=new Node(data,null); 194 break; 195 }else{ 196 temp=temp.next; 197 } 198 } 199 } 200 201 202 //遍历链表:因为头节点只存下一节点的地址而不存数据,所以从头节点的下一个节点开始遍历 203 public void showLink(){ 204 if(head.next==null){ 205 System.out.println("链表为空!!!"); 206 }else{ 207 Node temp=head.next; 208 while(true){ 209 if(temp.next==null){ //最后一个节点,打印后直接跳出循环 210 System.out.print(temp); 211 break; 212 }else{ 213 System.out.print(temp+","); 214 temp=temp.next; 215 } 216 } 217 } 218 System.out.println(); 219 } 220 221 222 223 /* 224 //排序: 225 public static void paiXu(NewLinkedList a,NewLinkedList b){ 226 System.out.println("排序如下:"); 227 Node ta=new Node(-1,null); 228 Node tb=new Node(-1,null); 229 Node temp=new Node(-1,null); 230 NewLinkedList c=null; 231 c.head=temp; 232 ta=a.head.next; 233 tb=b.head.next; 234 235 { 236 if(ta.data<tb.data){ 237 temp.next=ta; 238 temp=temp.next; 239 ta=ta.next; 240 }else{ 241 temp.next=tb; 242 temp=temp.next; 243 tb=tb.next; 244 245 } 246 }while(ta.next==null&&tb.next ==null) 247 248 249 250 if(ta.next!=null){ 251 temp.next=ta; 252 } 253 if(tb.next!=null){ 254 temp.next=tb; 255 } 256 c.showLink(); 257 258 259 } 260 261 */ 262 263 264 265 }
2.双向链表
2.1单向链表的缺点
(1)查找方向只能是一个方向;
(2)单向链表不能自我删除,所以单向链表删除节点时(记为B),只能先找到待删除节点的上一个节点(记为A),然后再让A.next指向B的下一个节点(记为C),即:A.next=A.next.next,完成删除B的任务,最后B会被垃圾回收机制回收;
而双向链表可以弥补单链表的缺点:
双向链表可以双向查找节点;双向链表可以进行自我删除
2.2 双向链表的增、删、改、查

1 package LianBiao; 2 /* 3 * 双向链表的增删改查 4 * 基本就是在单向链表的基础上做修改 5 * 6 */ 7 public class DoubleLinkedListDemo { 8 public static void main(String[] args){ 9 10 DoubleLinkedList dt=new DoubleLinkedList(); 11 12 dt.addNode(1, "宋江", "及时雨"); 13 dt.addNode(2, "卢俊义", "玉麒麟"); 14 dt.addNode(3, "吴用", "智多星"); 15 dt.addNode(4, "公孙胜", "入云龙"); 16 dt.addNode(5, "林冲", "豹子头"); 17 dt.addNode(6, "鲁智深", "花和尚"); 18 dt.addNode(7, "武松", "行者"); 19 dt.addNode(8, "李逵", "黑旋风"); 20 dt.addNode(9, "杨志", "青面兽"); 21 22 /* 23 System.out.println("---------------------------"); 24 dt.show(); 25 System.out.println("---------------------------"); 26 dt.backShow(); 27 System.out.println("---------------------------"); 28 dt.showHeadTail(); 29 System.out.println("---------------------------"); 30 */ 31 32 //dt.findNodeDouble(5); 33 //dt.deleteNodeDouble(8); 34 dt.show(); 35 System.out.println("--------------------"); 36 dt.modifyNodeDouble(9, "刘备", "玄德"); 37 dt.show(); 38 System.out.println("dt.tail---->"+dt.tail); 39 } 40 41 } 42 43 class HeroNode{ 44 int no; 45 String name; 46 String nickName; 47 HeroNode next; 48 HeroNode pre; 49 50 51 52 public HeroNode(int no, String name, String nickName, HeroNode next, HeroNode pre) { 53 super(); 54 this.no = no; 55 this.name = name; 56 this.nickName = nickName; 57 this.next = next; 58 this.pre = pre; 59 } 60 61 62 63 @Override 64 public String toString() { 65 return "座次: " + no + " 姓名: " + name + " 绰号: " + nickName; 66 } 67 68 } 69 70 class DoubleLinkedList{ 71 72 HeroNode head=new HeroNode(-1,"","",null,null); 73 HeroNode tail=new HeroNode(-1,"","",null,null); 74 75 /* 76 * 增加节点(默认加到尾部).和单向链表的方法基本一样,只是在末尾节点的指向上,使的添加节点的pre指向上一节点即可 77 */ 78 public void addNode(int no,String name,String nickName){ 79 HeroNode temp=head; 80 //遍历整个链表,寻找尾节点 81 while(true){ 82 if(temp.next==null){ 83 break; 84 }else{ 85 temp=temp.next; 86 } 87 } 88 89 temp.next=new HeroNode(no,name,nickName,null,temp); 90 tail=new HeroNode(no,name,nickName,null,temp); 91 } 92 93 94 95 96 97 //正向遍历 98 99 public void show(){ 100 System.out.println("****************"+tail); 101 if(head.next==null){ 102 System.out.println("链表为空!!!"); 103 }else{ 104 HeroNode temp=head.next; 105 while(true){ 106 if(temp==null){ 107 break; 108 }else{ 109 System.out.println(temp); 110 temp=temp.next; 111 } 112 } 113 114 } 115 } 116 117 118 //反向遍历 119 public void backShow(){ 120 long startTime=System.nanoTime(); 121 if(tail==null){ 122 System.out.println("链表为空"); 123 }else{ 124 HeroNode index=tail; 125 while(true){ 126 if(index==head){ 127 break; //当尾节点=头节点时,遍历完毕,退出 128 }else{ 129 System.out.println(index); 130 index=index.pre; 131 } 132 } 133 134 long endTime=System.nanoTime(); 135 System.out.println("运行耗时:"+(endTime-startTime)); 136 137 } 138 } 139 140 141 //双向遍历 142 public void showHeadTail(){ 143 long startTime=System.nanoTime(); 144 if(head.next==null){ 145 System.out.println("链表为空!!!"); 146 }else{ 147 HeroNode temp=head.next; 148 HeroNode index=tail; 149 boolean flag=true;//true:单数;false:双数 150 while(true){ 151 if(temp==index){ 152 flag=true;//单数 153 break; 154 } 155 if(temp.next==index){ 156 flag=false;//双数 157 break; 158 } 159 System.out.println(temp); 160 System.out.println(index); 161 temp=temp.next; 162 index=index.pre; 163 164 } 165 166 if(flag==true){ 167 System.out.println(temp); 168 }else{ 169 System.out.println(temp); 170 System.out.println(index); 171 } 172 173 long endTime=System.nanoTime(); 174 System.out.println("运行耗时:"+(endTime-startTime)); 175 } 176 } 177 178 //查找节点(单向正向查找) 179 public void findNode(int no){ 180 if(head.next==null){ 181 System.out.println("链表为空!!!"); 182 }else{ 183 HeroNode temp=head.next; 184 while(true){ 185 if(temp==null){ 186 System.out.println("查无此人"); 187 break; 188 }else{ 189 if(temp.no==no){ 190 System.out.println(temp); 191 break; 192 }else{ 193 temp=temp.next; 194 } 195 } 196 } 197 198 } 199 } 200 201 //查找节点(双向查找) 202 public void findNodeDouble(int no){ 203 if(head.next==null){ 204 System.out.println("链表为空!!!"); 205 }else{ 206 207 HeroNode temp=head.next; 208 HeroNode index=tail; 209 while(true){ 210 211 if(temp==index){ 212 if(temp.no==no){ 213 System.out.println(temp); 214 break; 215 }else{ 216 217 System.out.println("查无此人!!!"); 218 break; 219 } 220 } 221 if(index.next==temp){ 222 System.out.println("查无此人!!!"); 223 break; 224 } 225 226 227 if(temp.no==no){ 228 System.out.println(temp); 229 break; 230 } 231 if(index.no==no){ 232 System.out.println(index); 233 break; 234 } 235 temp=temp.next; 236 index=index.pre; 237 238 } 239 } 240 } 241 242 243 //删除节点(单向查找并删除) 244 public void deleteNode(int no){ 245 if(head.next==null){ 246 System.out.println("链表为空!!!"); 247 }else{ 248 HeroNode temp=head.next;//这里的指针指的是head 249 boolean flag=false; 250 while(true){ 251 if(temp==null){ 252 break; 253 }else{ 254 if(temp.no==no){ 255 flag=true; 256 break; 257 }else{ 258 temp=temp.next; 259 } 260 } 261 } 262 if(flag){ 263 if(temp.next==null){ 264 temp.pre.next=temp.next; 265 }else{ 266 temp.pre.next=temp.next; 267 temp.next.pre=temp.pre; 268 } 269 }else{ 270 System.out.println("无此人!!!"); 271 } 272 273 } 274 } 275 276 277 //删除节点(单向查找并删除) 278 public void deleteNode2(int no){ 279 if(head.next==null){ 280 System.out.println("链表为空!!!"); 281 }else{ 282 HeroNode temp=head.next;//这里的指针指的是head 283 while(true){ 284 if(temp.next==null){ 285 if(temp.no==no){ 286 //tail=null;//删除不了最后一个节点 287 temp.pre.next=null; 288 289 }else{ 290 System.out.println("无此人!!!"); 291 } 292 break; 293 }else{ 294 if(temp.no==no){ 295 temp.pre.next=temp.next; 296 temp.next.pre=temp.pre; 297 break; 298 }else{ 299 temp=temp.next; 300 } 301 } 302 } 303 304 305 } 306 } 307 308 309 //删除节点(双向遍历) 310 public void deleteNodeDouble(int no){ 311 if(head.next==null){ 312 System.out.println("链表为空!!!"); 313 }else{ 314 HeroNode temp=head.next; 315 HeroNode index=tail; 316 /* 317 * 1.判断是否删除的是最后一个节点 318 * 2.while循环 319 */ 320 if(tail.no==no){ 321 index.pre.next=null;//如果删除的是最后一个节点,则将其删除 322 }else{ 323 //若不是,则执行循环 324 while(true){ 325 if(temp==index){ //链表长度为单数,当前后指针相遇 326 if(temp.no==no){//如果相遇的节点是需要删除的节点,则将其删掉 327 temp.pre.next=temp.next; 328 temp.next.pre=temp.pre; 329 }else{ 330 //如果不是,则说明这条链表中没有找到符合删除条件的节点 331 System.out.println("无此人!!!"); 332 } 333 break; 334 } 335 if(index.next==temp){ //链表长度为双数时,若链表中没有符合删除条件的节点,则会出现这种情况,所以当出现这种情况,证明这条链表中没有找到符合删除条件的节点 336 System.out.println("无此人!!!"); 337 break; 338 } 339 if(temp.no==no){ 340 temp.pre.next=temp.next; 341 temp.next.pre=temp.pre; 342 break; 343 }else{ 344 temp=temp.next; 345 } 346 if(index.no==no){ 347 index.pre.next=index.next; 348 index.next.pre=index.pre; 349 break; 350 }else{ 351 index=index.pre; 352 } 353 354 } 355 356 } 357 } 358 } 359 360 361 //修改某个节点(单向遍历) 362 public void modifyNode(int no,String name,String nickName){ 363 364 } 365 366 //修改某个节点(双向遍历) 367 /* 368 * 存在一个问题:修改尾节点后,再进行单向正向遍历,发现尾节点是之前没有修改的,但是对尾节点进行打印发现是已经修改过的;而对其他节点的修改操作是成功的 369 * 而进行反向单向遍历以及双向遍历时,发现一切正常,修改功能可以正常实现 370 */ 371 372 public void modifyNodeDouble(int no,String name,String nickName){ 373 if(head.next==null){ 374 System.out.println("链表为空!!!"); 375 }else{ 376 HeroNode temp=head.next; 377 HeroNode index=tail; 378 while(true){ 379 if(temp==index){ //链表长度为单数,当前后指针相遇 380 if(temp.no==no){//如果相遇的节点是需要修改的节点,则修改 381 temp.name=name; 382 temp.nickName=nickName; 383 }else{ 384 //如果不是,则说明这条链表中没有找到符合条件的节点 385 System.out.println("无此人!!!"); 386 } 387 break; 388 } 389 if(index.next==temp){ //链表长度为双数时,若链表中没有符合条件的节点,则会出现这种情况,所以当出现这种情况,证明这条链表中没有找到符合条件的节点 390 System.out.println("无此人!!!"); 391 break; 392 } 393 if(temp.no==no){ 394 temp.name=name; 395 temp.nickName=nickName; 396 break; 397 }else{ 398 temp=temp.next; 399 } 400 if(index.no==no){ 401 index.name=name; 402 index.nickName=nickName; 403 break; 404 }else{ 405 index=index.pre; 406 } 407 408 } 409 System.out.println("打印尾节点----》"+tail); 410 } 411 } 412 413 }
问题:在modifyNodeDouble()方法中,如果修改的是尾节点,在使用show()正向单向遍历打印时,发现尾节点还是之前的那个,并未成功修改,而测试其他节点的修改时,发现可以修改成功;当使用backShow()反向单向遍历以及showHeadTail()双向遍历时,发现,所有位置的节点的修改功能都能成功实现。
在main()方法,以及show()方法,还有modifyNodeDouble()方法中,对tail进行打印:
main()方法中打印

show()方法中打印

modifyNodeDouble()方法中打印
![]()
发现tail的值都是修改后的值,那么问题可能就出在正向单向遍历那里:可能是当show()方法中的temp指针移到倒数第二个节点时,temp.next指针指的不是tail,而是原来之前未修改时的节点。这样导致即使修改了尾节点,但是采用这种遍历方法,遍历后还是原来之前未修改的值。
可是该如何解决这个问题???
3.单向环型链表及约瑟夫问题
约瑟夫问题:

1 package LianBiao; 2 /* 3 * 循环链表 4 */ 5 public class CircleLinkedListDemo { 6 public static void main(String[] args){ 7 8 ChildNode c1=new ChildNode(1,"佟湘玉"); 9 ChildNode c2=new ChildNode(2,"白展堂"); 10 ChildNode c3=new ChildNode(3,"郭芙蓉"); 11 ChildNode c4=new ChildNode(4,"吕秀才"); 12 ChildNode c5=new ChildNode(5,"李大嘴"); 13 ChildNode c6=new ChildNode(6,"莫小贝"); 14 ChildNode c7=new ChildNode(7,"老邢"); 15 ChildNode c8=new ChildNode(8,"燕小六"); 16 17 18 CircleLinkedList cl=new CircleLinkedList(); 19 cl.addNode(c1); 20 cl.addNode(c2); 21 cl.addNode(c3); 22 cl.addNode(c4); 23 cl.addNode(c5); 24 cl.addNode(c6); 25 cl.addNode(c7); 26 cl.addNode(c8); 27 cl.showNode(); 28 System.out.println("------------"); 29 cl.showByNum(1, 10); 30 System.out.println("------------"); 31 cl.showNode(); 32 33 34 } 35 36 } 37 38 class ChildNode{ 39 int no; 40 String name; 41 ChildNode next; 42 43 @Override 44 public String toString() { 45 return "no: " + no + ", name: " + name ; 46 } 47 48 public ChildNode(int no, String name) { 49 super(); 50 this.no = no; 51 this.name = name; 52 53 } 54 55 56 57 } 58 59 class CircleLinkedList{ 60 ChildNode first=new ChildNode(-1,null); 61 int num=0;//记录圈中成员个数 62 63 64 //添加节点--成功实现 65 public void addNode(ChildNode child){ 66 if(first.next==null){ 67 first=child; 68 first.next=first; 69 num++; 70 }else{ 71 ChildNode temp=first; 72 while(true){ 73 if(temp.next==first){ 74 break; 75 }else{ 76 temp=temp.next; 77 } 78 } 79 temp.next=child; 80 child.next=first; 81 num++; 82 83 } 84 85 } 86 87 //遍历节点--成功实现 88 public void showNode(){ 89 if(first.next==null){ 90 System.out.println("链表为空!!!"); 91 }else{ 92 ChildNode temp=first; 93 while(true){ 94 if(temp.next==first){ 95 System.out.println(temp); 96 break; 97 }else{ 98 System.out.println(temp); 99 temp=temp.next; 100 } 101 } 102 } 103 } 104 105 //测试是否是环形链表--成功 106 public void showNodeTest(){ 107 ChildNode temp=first; 108 while(true){ 109 System.out.println(temp); 110 temp=temp.next; 111 } 112 } 113 114 //约瑟夫问题--成功实现(存在的问题:运行完此功能后,原有链表结构被破坏) 115 /* 116 * @param startNo:表示从第几个人出数 117 * @param countNum:表示数几下 118 * @param total:表示圈中成员总数 119 */ 120 public void showByNum(int startNo,int countNum){ 121 System.out.println("出圈顺序为:"); 122 int total=num; 123 ChildNode last;//last指针,用来指向first的上一个节点 124 if(first==null){ 125 System.out.println("链表为空,请添加数据!!!"); 126 }else{ 127 if(startNo<1||startNo>total){ 128 System.out.println("非法输入!!!"); 129 }else{ 130 131 //找到开始数的成员,将first指针移到此处,同时将last指针移到其后面 132 ChildNode temp=first; 133 while(true){ 134 if(temp.next.no==startNo){ 135 last=temp; 136 first=temp.next; 137 break; 138 }else{ 139 temp=temp.next; 140 } 141 } 142 143 //开始循环 144 while(true){ 145 if(first.next==first){ 146 System.out.println(first); 147 break; 148 }else{ 149 for(int i=1;i<countNum;i++){ 150 first=first.next; 151 last=last.next; 152 } 153 System.out.println(first); 154 first=first.next; 155 last.next=first; 156 } 157 } 158 159 160 } 161 } 162 163 } 164 }


浙公网安备 33010602011771号