JAVA单循环链表和双循环链表简单操作
- 1、删除单循环链表某结点的直接前驱点
- 2、三个循环链表储存一个循环链表的不同类字符
- 3、有一双链表,每个结点中除有 prior、data 和 next 域外,还有一访问频度 域freq,在链表被启用前,其值均初始化为零。每当在链表上进行一次LOCATE(L,x) 运算,元素值为 x 的结点中 freq 域的值增 1,并使此链表中结点保持按 freq 递减 的顺序排列,以便使频繁访问的结点总是靠近表头。设计满足上述要求的LOCATE 算法。(问题描述是c/c++版的,使用JAVA写这段代码的时候是不需要传递LOCATE里面的L的,因为此时L是链表本身,L实际上就是this)
- 我们可以参考下面的图,可以以结点3为例画一下图(图中的结点1是不保存数据的,实际上未参与操作)
1、删除单循环链表某结点的直接前驱点
问题描述:假设在长度大于 1 的单循环链表中,既无头结点也无头指针。s 为指向某 个结点的指针,试编写算法删除结点*s 的直接前驱结点。
这里考虑的是:既然是删除某个节点的直接前驱,举个例子:假设现在我们有编号为 1 2 3 4 5 的5 个结点,现在我们要删除结点3的直接前驱结点,也就是2,那么只需要让结点 1 的next指向3就可以了,直接越过2,这样就实现了。
不过这里有一个问题,就是如果说输入 2,那么我们要删除1,也就是让5的next指向2,这时候会出错,我们需要加一个判定为表尾时的特殊情况
如果当前节点的下一个结点的下一个结点是我们输入的结点,那么就让当前结点的next指向下一个结点的下一个结点(这里要考虑一下当前结点是不是表尾的结点)
public void Delete(char e ){//删除某结点直接前驱结点的方法
Node_lp current=this.header;
// Node_lp p=this.header;
for (int i = 0; i < size; i++) {// O(n)
if (current.next.next.getData()==e) {//如果当前节点的下一个结点的下一个结点是我们输入的结点
if(tail.equals(current)){//如果当前结点是尾结点,那么让当前结点的指向下一个结点的下一个结点
current.setNext(current.next.next);
header=current.next;//然后此时需要修改header为当前结点的下一个结点,否则header仍然是原来的头节点
size--;
break;
}
current.setNext(current.next.next);//非特殊情况,同上
size--;
break;
}
current = current.next;
}
System.out.println("删除后的链表:"+this);
}
2、三个循环链表储存一个循环链表的不同类字符
问题描述:已知由单链表表示的线性表中,含有三类字符的数据元素(如:字母、 数字和其它字符),设计算法构造三个以循环链表示的线性表,使每一个表中只 含同一类的字符,且利用原表中的结点空间作为这三个表的空间。(头结点可以 另辟空间)
(实际上这里我偷懒了,没用原空间)
(实际上这里我偷懒了,没用原空间)
(实际上这里我偷懒了,没用原空间)
public void divi_3(){
Node current=header;
Loop_list a1=new Loop_list();
Loop_list a2=new Loop_list();
Loop_list a3=new Loop_list();
while(current!=null){//O(n)
if((current.getData()>='A' && current.getData()<='Z')||(current.getData()>='a' && current.getData()<='z')){
a1.add(current.data);
}
else if(current.getData()>='0' && current.getData()<='9'){
a2.add(current.data);
}
else{
a3.add(current.data);
}
current=current.next;
}
System.out.println("字母:"+a1);
System.out.println("数字:"+a2);
System.out.println("符号:"+a3);
}
3、有一双链表,每个结点中除有 prior、data 和 next 域外,还有一访问频度 域freq,在链表被启用前,其值均初始化为零。每当在链表上进行一次LOCATE(L,x) 运算,元素值为 x 的结点中 freq 域的值增 1,并使此链表中结点保持按 freq 递减 的顺序排列,以便使频繁访问的结点总是靠近表头。设计满足上述要求的LOCATE 算法。(问题描述是c/c++版的,使用JAVA写这段代码的时候是不需要传递LOCATE里面的L的,因为此时L是链表本身,L实际上就是this)
//这个链表在建立的时候是有头结点的,头节点里什么都没有存
public void LOCATE(char x){//O(n+m)
Node current=header.next;//操作的开始先略过空的头结点
int k;
while (current!=null&¤t.data!=x)//找到这个输入的x之前一直往下走
{
current=current.next;
}
Node tem=header.next;//让临时结点为第一个保存数据的结点
current.freq++;//当前结点值域+1
while(tem.freq>=current.freq){//让临时结点从头开始找,找到值域大于等于当前结点的那个结点
tem=tem.next;//让它向下走=移动一个
}
current.prior.next=current.next;//先将当前结点的前一个结点的next指向当前结点的后一个结点
current.next.prior=current.prior;//再将当前结点的后一个结点的prior指向当前节点的前一个结点
//此时当前结点只有piror和next连接它的前一个结点和后一个结点了
//但是它的前一个结点和后一个结点都不指向它了,我们可以认为已经把它从链表上“卸”下来了
current.prior=tem.prior;//此时再将当前结点的prior指向临时结点的前一个结点
current.next=tem;//再让当前结点的next指向临时结点
tem.prior.next=current;//然后让临时结点前一个结点的next指向当前结点,
tem.prior=current;//再把临时结点的prior指向当前结点,这样就把current又挂到链表上了
}
我们可以参考下面的图,可以以结点3为例画一下图(图中的结点1是不保存数据的,实际上未参与操作)
想看完整代码可以私信我(虽然写得很辣鸡)(我的图好像挂了 发不上来 有点可惜)