逻辑结构图:
先创建一个节点类:
为了简化代码链表中的真实数据均整形data表示,并用Num(Num从1开始)记录对应的下标。
public class Node {
int data;//链表中的真实数据
int Num;//对应下标
Node next;//指针
public Node(){}
public Node(int data){
this.data=data;
next=null;
}
public Node(int data,int Num){
this.data=data;
this.Num=Num;
}
然后创建一个单向链表类
public class DemoNdeList {
private Node first;
private Node last;
private int total;
public NodeList(){}
public boolean isEmpty(){}//判断链表是否为空
public void add(Node newNode){}//增加元素
public void delete(Node delNode){}//删除元素
public Node findElem(Node findNode){}//查找元素
public void revise(Node reNode){}//更改元素
public void insertElem(Node newNode){}//往中间插入元素
public void ergod(){}//遍历元素
public void reverseElem(){}//反转链表
}
接下来一一实现上述方法:
public boolean isEmpty(){
return first==null;
}
头插法
public void add(Node newNode){
if(isEmpty()){
first=newNode;
last=newNode;
}else{
last.next=newNode;
last=newNode;
}
newNode.Num=++total;
}
public void delete(Node delNode){
if(isEmpty()){
System.out.println("链表为空,无删除选项");
}
else if(delNode.Num==first.Num){
first=first.next;
Node newptr=first;
while(newptr!=null){
newptr.Num--;
newptr=newptr.next;
}
total--;
}
else if(delNode.Num==last.Num){
Node cur=first;
while(cur.next.Num!=last.Num)
cur=cur.next;
cur.next=null;
last=cur;
total--;
}
else {
Node cur = first;
Node ptr = first;
while (cur != null && cur.Num != delNode.Num) {//找到被修改元素
ptr = cur;
cur = cur.next;
}
if (cur != null) {
ptr.next = cur.next;
Node newptr = cur.next;
while (newptr != null) {
newptr.Num--;
newptr = newptr.next;
}
total--;
} else {
System.out.println("查无此元素");
}
}
}
public Node findElem(Node findNode){
if(isEmpty()){
System.out.println("链表为空,无法查找");
return null;
}
Node cur=first;
while(cur!=null&&cur.data!=findNode.data)
cur=cur.next;
return cur;
}
public void revise(Node reNode){
if(isEmpty()){
System.out.println("链表为空,无法查找");
return;
}
Node cur=first;
while(cur!=null&&cur.Num!=reNode.Num)
cur=cur.next;
if(cur!=null){
cur.data=reNode.data;
}else{
System.out.println("查无此元素");
}
注意这里的插入方法只涉及往中间插,不涉及头插与尾插。
public void insertElem(Node newNode){
if(isEmpty()){
first=newNode;
last=newNode;
return;
}
Node cur=first;
Node ptr=first;
while(cur!=null&&cur.Num!= newNode.Num) {//找到插入位置
ptr=cur;
cur = cur.next;
}
if(cur!=null){
ptr.next=newNode;
newNode.next=cur;
while(cur!=null){
cur.Num++;
cur=cur.next;
}
total++;
}
}
public void ergod(){
if(isEmpty()){
System.out.println("链表为空,无法遍历");
return;
}
Node cur=first;
while(cur!=null){
System.out.println(cur.Num+"\t"+cur.data);
cur=cur.next;
}
}
先用tmp记录cur.next,然后将cur指向的下一个结点的指针(cur.next)指向上一个结点(bef),如此反复,直到最后一个节点即可。
public void reverseElem(){
Node cur=first;
Node bef=null;
while(cur!=null){
Node tmp=cur.next;
cur.next=bef;
bef=cur;
cur=tmp;
}
first=bef;
}
public class NodeList {
private Node first;
private Node last;
private int total;
public NodeList(){}
//判断是否为空
public boolean isEmpty(){
return first==null;
}
//增加元素
public void add(Node newNode){
if(isEmpty()){
first=newNode;
last=newNode;
}else{
last.next=newNode;
last=newNode;
}
newNode.Num=++total;
}
//删除元素
public void delete(Node delNode){
if(isEmpty()){
System.out.println("链表为空,无删除选项");
}
else if(delNode.Num==first.Num){
first=first.next;
Node newptr=first;
while(newptr!=null){
newptr.Num--;
newptr=newptr.next;
}
total--;
}
else if(delNode.Num==last.Num){
Node cur=first;
while(cur.next.Num!=last.Num)
cur=cur.next;
cur.next=null;
last=cur;
total--;
}
else {
Node cur = first;
Node ptr = first;
while (cur != null && cur.Num != delNode.Num) {//找到被修改元素
ptr = cur;
cur = cur.next;
}
if (cur != null) {
ptr.next = cur.next;
Node newptr = cur.next;
while (newptr != null) {
newptr.Num--;
newptr = newptr.next;
}
total--;
} else {
System.out.println("查无此元素");
}
}
}
//查找元素
public Node findElem(Node findNode){
if(isEmpty()){
System.out.println("链表为空,无法查找");
return null;
}
Node cur=first;
while(cur!=null&&cur.data!=findNode.data)
cur=cur.next;
return cur;
}
//更改元素
public void revise(Node reNode){
if(isEmpty()){
System.out.println("链表为空,无法查找");
return;
}
Node cur=first;
while(cur!=null&&cur.Num!=reNode.Num)
cur=cur.next;
if(cur!=null){
cur.data=reNode.data;
}else{
System.out.println("查无此元素");
}
}
//往中间插入元素插入元素
public void insertElem(Node newNode){
if(isEmpty()){
first=newNode;
last=newNode;
return;
}
Node cur=first;
Node ptr=first;
while(cur!=null&&cur.Num!= newNode.Num) {//找到插入位置
ptr=cur;
cur = cur.next;
}
if(cur!=null){
ptr.next=newNode;
newNode.next=cur;
while(cur!=null){
cur.Num++;
cur=cur.next;
}
total++;
}
}
//遍历链表
public void ergod(){
if(isEmpty()){
System.out.println("链表为空,无法遍历");
return;
}
Node cur=first;
while(cur!=null){
System.out.println(cur.Num+"\t"+cur.data);
cur=cur.next;
}
}
//反转链表
public void reverseElem(){
Node cur=first;
Node bef=null;
while(cur!=null){
Node tmp=cur.next;
cur.next=bef;
bef=cur;
cur=tmp;
}
first=bef;
}
}
import java.util.Scanner;
public class DemoNdeList {
public static void menu(){
System.out.println(" 1.增加元素");
System.out.println(" 2.删除元素");
System.out.println(" 3.查找元素");
System.out.println(" 4.更改元素");
System.out.println(" 5.插入元素");
System.out.println(" 6.遍历链表");
System.out.println(" 7.反转链表");
System.out.println(" 8.退出");
}
public static void main(String[] args){
NodeList L=new NodeList();
Scanner sc=new Scanner(System.in);
boolean flag=true;
while(flag){
menu();
int key=sc.nextInt();
switch(key){
case 1:
System.out.println("请输入数字:");
int n1=sc.nextInt();
Node w1=new Node(n1);
L.add(w1);
break;
case 2:
System.out.println("请输入删除元素序列号:");
int n2=sc.nextInt();
Node w2=new Node();
w2.Num=n2;
L.delete(w2);
break;
case 3:
System.out.println("请输入查找元素数据:");
int n3=sc.nextInt();
Node w3=new Node(n3);
if(L.findElem(w3)!=null){
System.out.println("找到此元素,序列为:"+L.findElem(w3).Num);
}
break;
case 4:
System.out.println("请输入更改元素序列号:");
int n4=sc.nextInt();
System.out.println("请输入更改数字");
int n44=sc.nextInt();
Node w4=new Node(n44,n4);
L.revise(w4);
break;
case 5:
System.out.println("请输入要插入元素的数据");
int n5=sc.nextInt();
System.out.println("请输入将元素插入到的位置:");
int n55=sc.nextInt();
Node w5=new Node(n5,n55);
L.insertElem(w5);
break;
case 6:
System.out.println("链表遍历如下:");
L.ergod();
break;
case 7:
System.out.println("反转链表后,数据如下:");
L.reverseElem();
L.ergod();
break;
case 8:
System.out.println("退出程序完毕");
flag=false;
break;
default:
System.out.println("输入有误,请重新输入");
break;
}
}
}
}
public class Node {
int data;//链表中真实数据
int Num;//记录下标从一开始
Node lnext;//记录前一个节点或左边结点
Node rnext;//记录后一个结点或右结点
public Node(){}
public Node(int data){
this.data=data;
lnext=null;
rnext=null;
}
public Node(int data,int Num){
this.data=data;
this.Num=Num;
lnext=null;
rnext=null;
}
}
创建一个双向链表类:
public class DoubleLinkedList {
private Node first;
private Node last;
private int total;
public DoubleLinkedList(){}
public boolean isEmpty(){}//判断链表是否为空
public void add(Node newNode){}//增加元素
public void delete(Node delNode){}//删除元素
public Node findElem(Node findNode){}//查找元素
public void revise(Node reNode){}//更改元素
public void insertElem(Node newNode){}//往中间插入元素
public void ergod(){}//遍历元素
}
public boolean isEmpty(){
return first==null;
}
public void add(Node newNode){
if(isEmpty()){
first=newNode;
last=newNode;
}else{
newNode.lnext=last;
last.rnext=newNode;
last=newNode;
}
newNode.Num=++total;
}
public void delete(Node delNode){
if(isEmpty()){
System.out.println("链表为空,无删除选项");
}
else if(delNode.Num==first.Num){
first=first.rnext;
first.lnext=null;
Node newptr=first;
while(newptr!=null){
newptr.Num--;
newptr=newptr.rnext;
}
total--;
}
else if(delNode.Num==last.Num){
Node tmp=last.lnext;
last.lnext.rnext=null;
last.lnext=null;
last=tmp;
total--;
}
else {
Node cur = first;
while (cur != null && cur.Num != delNode.Num) {//找到被修改元素
cur = cur.rnext;
}
if (cur != null) {
cur.lnext.rnext=cur.rnext;
cur.rnext.lnext=cur.lnext;
Node newptr = cur.rnext;
while (newptr != null) {
newptr.Num--;
newptr = newptr.rnext;
}
total--;
} else {
System.out.println("查无此元素");
}
}
}
public Node findElem(Node findNode){
if(isEmpty()){
System.out.println("链表为空,无法查找");
return null;
}
Node cur=first;
while(cur!=null&&cur.Num!=findNode.Num)
cur=cur.rnext;//从头往后查找
return cur;
}
public void revise(Node reNode){
if(isEmpty()){
System.out.println("链表为空,无法查找");
return;
}
Node cur=first;
while(cur!=null&&cur.Num!=reNode.Num)
cur=cur.rnext;
if(cur!=null){
cur.data=reNode.data;
}else{
System.out.println("查无此元素");
}
}
public void insertElem(Node newNode){
if(isEmpty()){
first=newNode;
last=newNode;
return;
}
Node cur=first;
while(cur!=null&&cur.Num!= newNode.Num) {//找到被修改元素
cur = cur.rnext;
}
if(cur!=null){
newNode.lnext=cur.lnext;
cur.lnext.rnext=newNode;
newNode.rnext=cur;
cur.lnext=newNode;
while(cur!=null){
cur.Num++;
cur=cur.rnext;
}
total++;
}
}
public void ergod(){
if(isEmpty()){
System.out.println("链表为空,无法遍历");
return;
}
Node cur=first;
while(cur!=null){
System.out.println(cur.Num+"\t"+cur.data);
cur=cur.rnext;
}
}
public class DoubleLinkedList {
private Node first;
private Node last;
private int total;
public DoubleLinkedList(){}
//判断是否为空
public boolean isEmpty(){
return first==null;
}
//增加元素
public void add(Node newNode){
if(isEmpty()){
first=newNode;
last=newNode;
}else{
newNode.lnext=last;
last.rnext=newNode;
last=newNode;
}
newNode.Num=++total;
}
//删除元素
public void delete(Node delNode){
if(isEmpty()){
System.out.println("链表为空,无删除选项");
}
else if(delNode.Num==first.Num){
first=first.rnext;
first.lnext=null;
Node newptr=first;
while(newptr!=null){
newptr.Num--;
newptr=newptr.rnext;
}
total--;
}
else if(delNode.Num==last.Num){
Node tmp=last.lnext;
last.lnext.rnext=null;
last.lnext=null;
last=tmp;
total--;
}
else {
Node cur = first;
while (cur != null && cur.Num != delNode.Num) {//找到被修改元素
cur = cur.rnext;
}
if (cur != null) {
cur.lnext.rnext=cur.rnext;
cur.rnext.lnext=cur.lnext;
Node newptr = cur.rnext;
while (newptr != null) {
newptr.Num--;
newptr = newptr.rnext;
}
total--;
} else {
System.out.println("查无此元素");
}
}
}
//查找元素
public Node findElem(Node findNode){
if(isEmpty()){
System.out.println("链表为空,无法查找");
return null;
}
Node cur=first;
while(cur!=null&&cur.Num!=findNode.Num)
cur=cur.rnext;//从头往友查找
return cur;
}
//更改元素
public void revise(Node reNode){
if(isEmpty()){
System.out.println("链表为空,无法查找");
return;
}
Node cur=first;
while(cur!=null&&cur.Num!=reNode.Num)
cur=cur.rnext;
if(cur!=null){
cur.data=reNode.data;
}else{
System.out.println("查无此元素");
}
}
//往中间插入元素插入元素
public void insertElem(Node newNode){
if(isEmpty()){
first=newNode;
last=newNode;
return;
}
Node cur=first;
while(cur!=null&&cur.Num!= newNode.Num) {//找到被修改元素
cur = cur.rnext;
}
if(cur!=null){
newNode.lnext=cur.lnext;
cur.lnext.rnext=newNode;
newNode.rnext=cur;
cur.lnext=newNode;
while(cur!=null){
cur.Num++;
cur=cur.rnext;
}
total++;
}
}
//遍历链表
public void ergod(){
if(isEmpty()){
System.out.println("链表为空,无法遍历");
return;
}
Node cur=first;
while(cur!=null){
System.out.println(cur.Num+"\t"+cur.data);
cur=cur.rnext;
}
}
}
import java.util.Scanner;
public class DemoDoubleLinkedList {
public static void menu(){
System.out.println(" 1.增加元素");
System.out.println(" 2.删除元素");
System.out.println(" 3.查找元素");
System.out.println(" 4.更改元素");
System.out.println(" 5.插入元素");
System.out.println(" 6.遍历链表");
System.out.println(" 7.退出");
}
public static void main(String[] args){
DoubleLinkedList D=new DoubleLinkedList();
Scanner sc=new Scanner(System.in);
boolean flag=true;
while(flag){
menu();
int key=sc.nextInt();
switch(key){
case 1:
System.out.println("请输入数字:");
int n1=sc.nextInt();
Node w1=new Node(n1);
D.add(w1);
break;
case 2:
System.out.println("请输入删除元素序列号:");
int n2=sc.nextInt();
Node w2=new Node();
w2.Num=n2;
D.delete(w2);
break;
case 3:
System.out.println("请输入查找元素数据:");
int n3=sc.nextInt();
Node w3=new Node(n3);
if(D.findElem(w3)!=null){
System.out.println("找到此元素,序列为:"+D.findElem(w3).Num);
}
break;
case 4:
System.out.println("请输入更改元素序列号:");
int n4=sc.nextInt();
System.out.println("请输入更改数字");
int n44=sc.nextInt();
Node w4=new Node(n44,n4);
D.revise(w4);
break;
case 5:
System.out.println("请输入要插入元素的数据");
int n5=sc.nextInt();
System.out.println("请输入将元素插入到的位置:");
int n55=sc.nextInt();
Node w5=new Node(n5,n55);
D.insertElem(w5);
break;
case 6:
System.out.println("链表遍历如下:");
D.ergod();
break;
case 7:
System.out.println("退出程序完毕");
flag=false;
break;
default:
System.out.println("输入有误,请重新输入");
break;
}
}
}
}
环形链表和单项链表差不多,只不过是将首尾连接了起来形成一个环;
也是先创建一个结点:
public class Node {
int data;
Node next;
public Node(){}
public Node(int data){
this.data=data;
next=null;
}
}
这里仅展示增加和遍历方法,其余方法可借鉴单向链表中的方法
public class CircleLink {
private Node first;
private Node last;
public void add(Node newNode){
if(first==null){
first=newNode;
last=newNode
last.next=first;
}else {
last.next = newNode;
newNode.next = first;
last = newNode;
}
}
//遍历环形链表
public void show(){
Node empty=first;
if(empty==null){
System.out.println("链表为空,无法遍历");
return;
}
do{
System.out.printf("this is %dth data\n",empty.data);
empty=empty.next;
}while(empty!=first);
}
}
有n个人,编号为1~n,从第一个人开始报数,从1开始报,报到m的人会死掉,然后从第m+1个人开始,重复以上过程。在死了n-1个人后,问最后一个人的编号是?
public class CircleLink {
private Node first;
private Node last;
public void add(int n){
for(int i=1;i<=n;i++){
Node newNode=new Node(i);
if(first==null){
first=newNode;
last=newNode;
}
last.next=newNode;
last=newNode;
}
last.next=first;
}
//解决约瑟夫问题
public int solveJ(int n,int m){
if(m == 1 || n < 2){
System.out.println("输入参数有误");
return 0;
}
add(n);
int count=1;
Node cur=first;
Node ptr=null;
while(cur.next!=cur){
if(count==m){
ptr.next=cur.next;
cur=ptr.next;
count=1;
}else{
ptr=cur;
cur=cur.next;
count++;
}
}
return cur.data;
}
//遍历环形链表
public void show(){
Node empty=first;
if(empty==null){
System.out.println("this list is null");
return;
}
do{
System.out.printf("this is %dth data\n",empty.data);
empty=empty.next;
}while(empty!=first);
}
}