编程经验谈JAVA Web第11章 细说Java Web常用算法20例Word文档格式.docx
《编程经验谈JAVA Web第11章 细说Java Web常用算法20例Word文档格式.docx》由会员分享,可在线阅读,更多相关《编程经验谈JAVA Web第11章 细说Java Web常用算法20例Word文档格式.docx(87页珍藏版)》请在冰豆网上搜索。
说明:
上述代码中,公共成员Value用于储存节点本身的数据,Next用于存储下一个节点的指针。
对于链表的操作,无非是进行节点的查找、插入和删除操作。
1.查找节点
在进行节点查找时,通常根据节点的数据查找节点。
要实现节点的查找,首先需要解决的问题就是遍历链表中的所有节点。
可以从链表头节点开始,利用循环的方式向下查找,如果当前节点指向的下一个节点不为空,则将下一个节点设置为当前节点。
2.插入节点
插入节点需要考虑两种情况。
第一种情况是在链表尾节点处插入节点,这种情况比较简单,只要将当前尾节点的FNextNode(指向下一个节点的指针)指向新插入的节点就可以了。
第二种情况是在链表的中间位置插入节点,首先需要确定在哪个节点后插入新的节点,这就应该由用户来确定了,本例中为了演示的需要,笔者将树视图控件中的当前选项设置为当前节点。
然后需要记录当前节点的下一个节点(避免发生“脱节”),可以定义一个临时的节点进行记录。
将当前节点的下一个节点指向新添加的节点,再将新添加节点的下一个节点指向临时节点,整个插入节点的流程如图11.02所示。
图11.02插入节点示意图
3.删除节点
删除节点与插入节点类似,也需要考虑两种情况。
第一种情况是删除尾节点,这种情况操作相对比较简单,首先找到尾节点之前的一个节点,将该节点指向的下一个节点设置为空,然后释放尾节点资源。
第二种情况是删除链表中间部分的节点。
首先需要找到当前节点的下一个节点,并将当前节点指向下一节点下一,并释放当前节点的下一节点,整个流程如图11.03所示。
图11.03删除节点示意图
算法实现
链表是一种特殊的数据结构,能够动态的存储一种结构类型数据。
在开发复杂的系统时,经常会使用链表存储数据。
在本例中,笔者设计了一个单向链表。
例11.1实现单向链表的算法(光盘位置:
光盘\MR\Instance\11\01\11.1)
首先需要实现自定义的节点类,该类的实现方法可以参看本节算法点拨中的代码。
定义结点之后,开始类线性表的操作编程了。
在LIST类中,采用了Head、Tail、Current三个指针,使用Append、MoveFrist,MovePrevious、MoveNext、MoveLast、Delete、InsertAscending、InsertUnAscending、Clear实现移动、添加、删除、升序插入、降序插入、清空链表操作,并用GetCurrentValue方法取得当前的值。
在构造函数中初始化,并定义指针变量。
代码如下:
publicclassClist{
privateListNodeHead;
//头指针
privateListNodeTail;
//尾指针
privateListNodeCurrent;
//当前指针
privateintListCountValue;
//链表数据的个数
publicClist(){//构造函数
ListCountValue=0;
//初始化
Head=null;
//头指针为空
Tail=null;
//尾指针为空
向链表中尾部添加数据的代码如下:
publicvoidAppend(intDataValue){
ListNodeNewNode=newListNode(DataValue);
//初始化节点
if(ListCountValue==0){//如果链表为空
//头节点和尾节点都是该值
Head=NewNode;
Tail=NewNode;
else{
Tail.Next=NewNode;
//尾指针指向添加的数据
//尾节点为新添加的数据
Current=NewNode;
//当前节点为尾节点
ListCountValue+=1;
//链表数据个数加1
在当前位置后插入数据的代码如下:
publicvoidInsert(intDataValue){
if(ListCountValue==0){//如果链表为空
Append(DataValue);
//为空表,则添加
return;
//跳出程序
if(Current==Head){//如果当前节点为头结点
//为头部插入
NewNode.Next=Head;
//新结点的指针指向原来的头节点
//新节点为头结点
Current=Head;
//当前节点为头节点
ListCountValue+=1;
//节点数加1
if(Current==Tail){//若当前节点为尾节点
//尾节点就为当前节点指向的前一个节点
Tail=NewNode;
Current=Tail;
//节点数加1
//中间插入
if((Current!
=Head)&
&
(Current!
=Tail)){
NewNode.Next=Current.Next;
//将当前节点的指针赋值给新节点的指针
Current.Next=NewNode;
Current=NewNode;
ListCountValue+=1;
删除当前数据后的数据的代码如下:
publicvoidDelete(){
if(ListCountValue!
=0){//若链表不为空
if(Current==Head){//若当前节点为头结点
Head=Current.Next;
//头结点为当前节点指定的下个节点
//当前节点为头结点
ListCountValue-=1;
//节点数减1
}else{
Current=Current.Next;
//若从链表中间删除数据
//节点数减1
}
为了检查创建链表的正确性,特别创建了一个名称为Test的类,测试单向链表的添加和删除的操作,其关键代码如下:
publicclassTest{
publicstaticvoidmain(String[]args){
Clistclist=newClist();
clist.Append(12);
//添加尾节点
clist.Append(10);
clist.Insert(66);
//插入新节点
clist.Insert(33);
clist.Delete();
//删除节点
clist.printAllListNode();
//输出链表中所有的数据
运行上面的代码后,在控制台输出的信息如图11.04所示。
图11.04运行测试类后在控制台输出的链表中的数据
其中遍历链表打印数据的printAllListNode()方法关键代码如下:
//输出链表的值
publicvoidprintAllListNode(){
if(!
IsNull()){
System.out.println("
输出链表中的所有数据:
"
);
//当前节点为头结点
for(inti=0;
i<
ListCountValue;
i++){
System.out.println(Current.Value);
//输出当前节点值
Current=Current.Next;
//当前节点为下一个节点
算法02双线联系——双向链表算法
双向链表是一种常用的数据结构,是对链表的一种改进,双向链表允许向前遍历,也允许向后遍历。
本节将详细的介绍双向链表。
单向链表结构如图11.05所示。
图11.05双向链表结构
publicListNodePrevious;
//前节点
//后节点
上述代码中,公共成员Value用于储存节点本身的数据,Next用于存储下一个节点的指针,Previous用于存储上一个节点的指针。
将当前节点的下一个节点指向新添加的节点,再将新添加节点的下一个节点指向临时节点,整个插入节点的流程如图11.06所示。
图11.06插入节点示意图
首先需要找到当前节点的上一个节点,并定义一个临时节点PriorNode进行记录,然后再定义一个临时节点TempNode记录当前节点的下一个节点,最后将PriorNode的下一个节点指向TempNode,并释放当前节点,整个流程如图11.07所示。
图11.07删除节点示意图
例11.2实现单向链表的算法(光盘位置:
光盘\MR\Instance\11\02\11.2)
publicclassClist{
//头指针
//尾指针
//当前指针
//链表数据的个数
publicClist(){//构造函数
//初始化
//头指针为空
//尾指针为空
if(IsNull()){//如果链表为空
Tail.Next=NewNode;
//尾指针指向添加的数据
NewNode.Previous=Tail;
//数据的前一个指针指向原来的尾节点
Tail=NewNode;
//链表数据个数加1
在当前位置前插入数据的代码如下:
publicvoidInsert(intDataValue){
if(IsBof()){//如果当前节点为头结点
//先结点的后指针指向原来的头节点
Head.Previous=NewNode;
//原来的头结点的前指针指向新添加的节点
Current=Head;
NewNode.Next=Current;
//新节点的后指针指向当前节点
NewNode.Previous=Current.Previous;
//新节点的前指针指向当前节点的前一个节点
Current.Previous.Next=NewNode;
//当前节点的前一个节点的后指针指向前一个
Current.Previous=NewNode;
//当前节点的前指针指向新节点
//当前节点为新节点
//链表节点数加1
删除当前的数据的代码如下:
publicvoidDelete(){
=0){//若链表不为空
if(IsBof()){//若当前节点为头结点
//头结点为当前节点指定的下个节点
//当前节点为头结点
//节点数减1
//跳出程序
if(IsEof()){//若当前节点为尾节点
Tail=Current.Previous;
//尾节点就为当前节点指向的前一个节点
Current=Tail;
//当前节点为尾节点
//节点数减1
Current.Previous.Next=Current.Next;
//若从链表中间删除数据
Current=Current.Previous;
//当前节点为前一个节点
运行上面的代码后,在控制台输出的信息如图11.08所示。
图11.08运行测试类后在控制台输出的链表中的数据
算法03先进后出——堆栈
栈是一种常用的数据结构,在生活中经常遇到这样的例子,如铁路调度站。
本节将详细介绍堆栈的实现过程。
算法点拨(顺序栈)
栈是一种重要的数据结构。
从数据结构的角度看,栈也是线性表,其特殊性在于栈的基本操作是线性表操作的子集,它们是操作受限的线性表,因此可以称为限定性的数据结构。
其操作是限定在表尾进行插入和删除操作,允许操作的一端称为栈顶。
栈的结构如图11.09所示:
图11.09栈的结构
实现栈首先需要实现一个栈内元素,关键代码如下:
publicclassStack{
privateintmaxSize;
privateintstackArray[];
privateinttop=-1;
publicStack(ints){//构造方法
maxSize=s;
stackArray=newint[maxSize];
上述代码中,公共成员stackArray用于储存栈中的数据,top用于存储下一个数据元素的指针。
对于栈的操作,无非是进行数据元素的入栈与出栈。
1.查找栈中元素
在进行栈中元素查找时,通常根据栈中元素的数据查找节点。
要实现栈中元素的查找,首先需要解决的问题就是遍历栈中的所有元素。
可以从栈顶开始,利用循环的方式向下查找,只要不到栈底就可循环查找。
2.入栈操作
入栈操作前面说过,只能在栈顶操作。
先将top指针向后移动一个单位,然后将想要入栈的数据元素放到原来top指针所指向的元素位置即可。
这样就实现了对栈的入栈操作。
操作流程如图11.10所示:
图11.10入栈操作示意图
3.出栈操作
出栈操作和入栈操作的限定差不多,只是将整个过程反过来进行。
先将数据元素释放掉,然后在进行指针的操作,将栈顶指针top向前移动一个位置,使其位置在其原来所指向的位置。
将栈顶元素的指针域的指针的指向位置变为原来元素的指向位置。
出栈的操作流程如图11.11所示
图11.11删除节点示意图
栈是限定仅在表尾进行插入或删除操作的线性表。
因此对栈来说,表尾端有其特殊含义。
例11.3实现栈的算法(光盘位置:
光盘\MR\Instance\11\03\11.3)
首先需要实现自定义的数据元素类,该类的实现方法可以参看本节算法点拨中的代码。
定义数据元素之后,开始栈的操作编程了。
在类中,采用了push,pop,isEmpty,isfull,s等方法进行入栈,出栈,判断栈是否为空,判断栈是否满和对栈进行输出。
向栈中添加数据的代码如下:
publicvoidpush(intj){//入栈方法
stackArray[++top]=j;
//栈顶指针后移
对栈进行出栈的操作的代码如下:
publicintpop(){//出栈方法
returnstackArray[top--];
//栈顶指针前移
对栈是否为空和是否已满以及输出的判断代码如下:
publicbooleanisEmpty(){//判断栈是否为空