完整的代码地址为: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("插入成功");
else
System.out.println("插入失败(原因可能是你输入的前驱和后继即诶但均不存在)");
}
return head;
}
//查找并插入节点
boolean linkFindNode(DoubleLink head, String priorKey, String nextKey,Data nodeData) {
// TODO Auto-generated method stub
DoubleLink htemp=null,node=null;
if( (node = new DoubleLink()) == null )
{
System.out.println("内存分配失败");
return false;
}
//将传进来的值赋值给node
node.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; //将查找到的节点的后继节点指向node
node.nextNode = null;
node.priorNode = htemp;
return true;
}
else
System.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;
}
else
System.out.println("你输入的数字不合法!!!");
}
else //如果当前节点的后继节点不为空,则执行下一个节点
{
htemp = htemp.nextNode; //若当前节点没找到,遍历下一个节点
}
}
else
htemp = 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;
}
}
else
htemp = 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));
}
}
}
结果展示