《链表》——单向链表和双向链表(Java)

来源:互联网 发布:淘宝高仿鞋子店铺名字 编辑:程序博客网 时间:2024/06/04 23:26

完整的代码地址为:github  点击查看

单链表

单链表包括数据域和指向下一个节点的指针域,其结构如上图所示

首先定义一个数据类:

class DATA{           //定义链表的一个节点String key;           //节点的关键字String name;int age;}

定义一个单向链表类(包括以下几种方法):

1:在尾部添加节点

2:在头部添加节点

3:查找节点

4:插入节点

5:删除节点

6:计算链表长度

7:显示所有节点对应的代码如下

public class Link {     //定义链表结构DATA nodeData = new DATA();     //声明一个节点Link nextNode;                                //指向下一个节点的指针//添加节点Link linkAddEnd(Link head, DATA nodeData){Link node, hTemp;if( (node = new Link()) ==null)        //如果内存空间分配失败,则返回为空{System.out.println("内存空间分配失败!");return null;}else{node.nodeData = nodeData;node.nextNode = null;if(head == null)      //如果头节点为空,则把当前节点赋给head,并返回{head = node;return head;}      hTemp = head;       //如果头节点不为空while(hTemp.nextNode!=null)        //查找链表的末尾{hTemp = hTemp.nextNode;}hTemp.nextNode = node;return head;}}//插入头节点Link linkAddFirst(Link head, DATA nodeData){Link node;if((node=new Link()) == null ) //如果内存空间分配失败,则返回为空{System.out.println("内存分配失败");return null;}else{node.nodeData = nodeData;node.nextNode = head;head = node;return head;}}//查找节点Link linkFindNode(Link head, String key){Link hTemp;hTemp = head;while(hTemp!=null)       //若节点有效,则进行查找{if(hTemp.nodeData.key.compareTo(key) == 0) //若节点的关键字与传入的关键字相同{return hTemp;}hTemp = hTemp.nextNode;     //处理下一个节点}return null;}//插入节点Link linkInsertNode(Link head, String findKey,DATA nodeData){Link node,hTemp;if((node = new Link() ) == null ) //分配内存失败,则返回{System.out.println("分配内存失败...");return null;}node.nodeData = nodeData;      //保存当前集节点信息hTemp = linkFindNode(head, findKey);      //查找要插入的节点if(hTemp != null){node.nextNode = hTemp.nextNode;hTemp.nextNode = node;}else{System.out.println("未找到正确的插入位置.........");}return head;          //返回头引用}//删除节点int linkDeleteNode(Link head, String key){Link node,hTemp;hTemp = head;node = head;while(hTemp != null ){if(hTemp.nodeData.key.compareTo(key) == 0)   //若找到关键字,则删除{node.nextNode = hTemp.nextNode;hTemp = null;return 1;}else               //跳到下一个节点{node = hTemp;hTemp = hTemp.nextNode;}}return 0;}//计算链表长度int linkLength(Link head){Link hTemp;hTemp = head;int num = 0;while(hTemp!=null){num ++ ;hTemp = hTemp.nextNode;}return num;}//显示所有节点void linkShow(Link head){Link hTemp;DATA nodeData;hTemp = head;System.out.printf("当前链表共有 %d 个节点,链表所有的数据如下:\n" , linkLength(head));while(hTemp!=null){nodeData = hTemp.nodeData;     //获取当前的节点数据System.out.printf("节点(%s %s  %d)\n",nodeData.key,nodeData.name,nodeData.age);hTemp = hTemp.nextNode;}}}


编写测试类:

public class linkTest {public static void main(String[] args) {Link node = null , head=null;Link link = new Link();String key, findKey;Scanner input = new Scanner(System.in);System.out.printf("链表测试开始,先输出链表中的数据,格式为:关键字姓名年龄\n");do{                        //循环插入节点,知道输入的key 为0 结束DATA nodeData = new DATA();nodeData.key = input.next();if(nodeData.key.equals("0")){break;}else{nodeData.name = input.next();nodeData.age = input.nextInt();head = link.linkAddEnd(head, nodeData);  //在链表尾部添加节点}}while(true);link.linkShow(head);     //显示所有节点System.out.printf("\n演示插入节点,输入插入位置的关键字:");findKey = input.next();                //输入插入的关键字System.out.println("输入插入节点的数据(关键字 姓名 年龄)");DATA nodeData = new DATA();              //输入节点的元素值nodeData.key = input.next();nodeData.name = input.next();nodeData.age = input.nextInt();head = link.linkInsertNode(head, findKey, nodeData);           //调用插入函数link.linkShow(head);    //显示所有节点System.out.println("演示删除节点,输入要删除的关键字:");key = input.next();link.linkDeleteNode(head, key);         //调用删除节点的函数link.linkShow(head);                     //显示所有节点System.out.println("演示在链表中差找,输入要查找的关键字:");key = input.next();node = link.linkFindNode(head, key);  //调用查找函数,返回节点引用if(node!=null){nodeData = node.nodeData;         //获取节点的数据System.out.printf("关键字 %s 对应的节点数据为 (%s %s %s)\n", key,nodeData.key,nodeData.name,nodeData.age);}else{System.out.printf("在链表中为查找的为%s 的关键字 \n" , key);}}}


双向链表

链结点的结构:

┌────┬────┬────────┐

│data│next│previous│

└────┴────┴────────┘

结构图如下:



package Link;import java.util.Scanner;class Data{           //定义链表的一个节点String key;           //节点的关键字,唯一String name;int age;}public class DoubleLink {int flag; //输入选择值Scanner scan = new Scanner(System.in);Data data = new Data();DoubleLink nextNode;  //后继节点DoubleLink priorNode;    //前驱节点//链表添加节点DoubleLink addNode(DoubleLink head, String priorKey, String nextKey, Data nodeData){DoubleLink node=null, htemp=null;if((node = new DoubleLink()) == null)System.out.println("内存空间分配失败");if(head== null)        //如果head为空{System.out.println("当前链表为空,是否将当前节点当作头节点?\n0:否\t1:是");node.data=nodeData;node.nextNode=null;node.priorNode=null;flag = scan.nextInt();switch(flag){case 0:break;case 1:head=node;break;default:System.out.println("你输入的数据不合法");;}}       //如果head不为空else{if(linkFindNode(head, priorKey,nextKey,nodeData))System.out.println("插入成功");elseSystem.out.println("插入失败(原因可能是你输入的前驱和后继即诶但均不存在)");}return head;}//查找并插入节点boolean linkFindNode(DoubleLink head, String priorKey, String nextKey,Data nodeData) {// TODO Auto-generated method stubDoubleLink htemp=null,node=null;if( (node = new DoubleLink()) == null ){System.out.println("内存分配失败");return false;}//将传进来的值赋值给nodenode.data = nodeData;node.nextNode = null;node.priorNode=null;//两大类情况htemp = head;while(htemp != null){if(htemp.data.key.equals(priorKey)) //前驱节点存在{if(htemp.nextNode == null)     //该节点的后继节点为空,说明该节点为头节点{System.out.println("你输入的后继节点不存在,前驱节点为头节点,是否插入在其后面?\n 1:是 \t 0 :否 ");flag = scan.nextInt();if(flag == 0)break;else if(flag==1){htemp.nextNode = node;       //将查找到的节点的后继节点指向nodenode.nextNode = null;node.priorNode = htemp;return true;}elseSystem.out.println("你输入的数字不合法!!!");}else             //后继节点不为空{if(htemp.nextNode.data.key.equals(nextKey))            //存在的后继节点与nextKey相同。相同执行if{node.nextNode = htemp.nextNode;htemp.nextNode.priorNode = node;htemp.nextNode = node;node.priorNode = htemp;return true;}else         //不同执行else{htemp = htemp.nextNode; //若当前节点没找到,遍历下一个节点}}}else //前驱节点不存在,后驱节点存在{if(htemp.data.key.equals(nextKey))      //如果当前节点与nextKey相同{if(htemp.nextNode==null)  //如果后继节点为空,即当前节点为尾节点{System.out.println("你输入的前驱节点不存在,后继节点为头节点,是否插入在其前面?\n 1:是 \t 0 :否 ");flag = scan.nextInt();if(flag == 0)break;else if(flag==1){htemp.priorNode = node;node.nextNode = htemp;node.priorNode=null;return true;}elseSystem.out.println("你输入的数字不合法!!!");}else //如果当前节点的后继节点不为空,则执行下一个节点{htemp = htemp.nextNode; //若当前节点没找到,遍历下一个节点}}elsehtemp = htemp.nextNode; //若当前节点没找到,遍历下一个节点}}return false;}//输出节点public void OutputLinkNode(DoubleLink head){if(head == null)System.out.println("当前链表为空");else{System.out.println("输入的链表数据如下:");DoubleLink htemp;htemp = head;while(htemp!=null){System.out.println(htemp.data.key + "\t" + htemp.data.name + "\t" + htemp.data.age);htemp= htemp.nextNode;}}System.out.println();}//输出链表的深度int LinkDepth(DoubleLink head){int sum = 0;DoubleLink htemp = head;while(htemp!=null){sum ++;htemp = htemp.nextNode;}return sum;}//查找节点DoubleLink FindLink(DoubleLink head, String findKey){DoubleLink htemp=head;while(htemp!=null){if(htemp.data.key.equals(findKey))return htemp;htemp = htemp.nextNode;}return null;}//删除节点DoubleLink DeleteNode(DoubleLink head, String deleteKey){DoubleLink htemp = head;while(htemp!=null){if(htemp.data.key.equals(deleteKey)){if(htemp.priorNode==null)  //如果是头节点{return htemp.nextNode;}else if (htemp.nextNode==null)     //如果是尾节点{htemp.priorNode.nextNode=null;htemp.priorNode=null;return head;}else //如果是中间{htemp.priorNode.nextNode=htemp.nextNode;htemp.nextNode.priorNode = htemp.priorNode;return head;}}elsehtemp = htemp.nextNode;}System.out.println("你要删除的节点不存在!");return head;}}

测试实现:

package Link;import java.util.Scanner;public class DoubleLinkTest {public static void main(String[] args) {DoubleLink node=null, head=null;DoubleLink dlink = new DoubleLink(); //声明一个双向链表对象Scanner scan  = new Scanner(System.in);System.out.println("双向链表测试开始....");do{System.out.println("请输入插入节点的关键字,姓名和年龄,格式为:关键字姓名年龄");Data data = new Data();data.key = scan.next();data.name = scan.next();data.age = scan.nextInt();if(data.key.contains("0"))  //循环插入节点,直到插入的为0时结束break;else{System.out.println("请输入插入节点的前驱节点和后继节点,格式为 前驱节点  后继节点");String priorKey = scan.next();String nextKey = scan.next();head = dlink.addNode(head, priorKey, nextKey, data);   //添加节点 dlink.OutputLinkNode(head);   //输出链表}}while(true);//输出链表的深度System.out.println("该链表的深度为:" + dlink.LinkDepth(head));//查找链表中的某个节点System.out.println("请输入要查找的节点的关键字...");String findKey = scan.next();node = dlink.FindLink(head, findKey); if(node==null) System.out.println("你所查找的节点不存在!"); else System.out.println("该节点的值为:" + node.data.key + "\t" + node.data.name + "\t" + node.data.age); //删除节点值 System.out.println("请输入要删除的节点的关键字..."); String deleteKey = scan.next(); node =  dlink.DeleteNode(head, deleteKey); if(node == null) System.out.println("删除节点后的链表为空,其深度为:" + 0); else { System.out.println("删除后的链表为:"); dlink.OutputLinkNode(head); System.out.println("删除节点后链表的深度为:" + dlink.LinkDepth(head)); }}}

结果展示


0 0
原创粉丝点击