Node类
package com.doubluelinklist.test;
public class Node {
private int id; //编号
private String name; //姓名
public Node pre; //前一个结点
public Node next; //下一个结点
public Node(int id,String name){
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Node getPre() {
return pre;
}
public void setPre(Node pre) {
this.pre = pre;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
@Override
public String toString() {
return "id = " + this.getId() + "\t" + "name = " + this.getName();
}
}
DoubleLikeListSample类
package com.doubluelinklist.test;
import java.util.Stack;
public class DoubleLikeListSample {
private int size; //记录结点个数的变化
private Node head = new Node(0,""); //头结点,值为空,表示一个空结点
/*
* 1.结点的个数
* 2.获得头结点
* 3.判断结点是否存在,即加入的结点的编号是否已经存在
* 4.插入:
* 1.尾部加入
* 2.头部加入
* 3.指定位置插入
* 5.删除
* 1.指定位置删除
* 2.指定编号删除
* 3.指定姓名删除
* 6.修改
* 1.根据编号进行修改
* 2.根据姓名进行修改
* 7.根据编号进行排序
* 8.两个有序双链表进行合并
* 9.打印
* 10.从尾到头打印单链表
* 11.双向链表反转
* 12.查找单链表中的倒数第k个结点
*/
/*
* 1.结点的个数
*/
public int getSize(){
return size;
}
/*
* 2.获得头结点
*/
public Node getHead(){
return head;
}
/*
* 3.判断结点是否已经存在
*/
private boolean ifNodeNumberExists(Node node){
Node tmp = head.next;
for (int i = 1; i <= size; i++) {
if(node.getId() == tmp.getId()){
System.out.println("结点已经存在!!!");
return true;
}
tmp = tmp.next;
}
return false;
}
/*
* 4.1尾部加入
*/
public void add(Node node){
Node tmp = head;
//判断结点是否存在
if(ifNodeNumberExists(node)){
return;
}
if(head.next == null){
head.next = node;
node.pre = head;
}else{
for (int i = 1; i <= size; i++) {
tmp = tmp.next;
}
tmp.next = node;
node.pre = tmp;
}
node.next = null;
size++;
}
/*
* 4.2头部加入
*/
public void add2(Node node){
//判断结点是否已经存在
if(ifNodeNumberExists(node)){
return;
}
if(head.next == null){
head.next = node;
node.pre = head;
node.next = null;
}else{
node.next = head.next;
head.next.pre = node;
head.next = node;
node.pre = head;
}
size++;
}
/*
* 4.3指定位置插入
*/
public void add3(int index,Node node){
Node tmp = head;
//判断结点是否存在
if(ifNodeNumberExists(node)){
return;
}
//判断指定的位置是否正确
if(index < 1 || index > size + 1){ //设置为 > size + 1,表示可以在结尾加入
System.out.println("插入的位置不正确!!!");
return;
}
//得到指定位置的前一个结点
for (int i = 1; i < index; i++) {
tmp = tmp.next;
}
if(tmp.next != null){
node.next = tmp.next;
tmp.next.pre = node;
tmp.next = node;
node.pre = tmp;
}else{
//相当于在尾部加入了或者当只有头结点的时候
node.pre = tmp;
tmp.next = node;
node.next = null;
}
size++;
}
/*
* 5.1指定位置删除
*/
public void indexDetleNode(int index){
Node tmp = head;
//判断是否为空链表
if(head.next == null){
System.out.println("空链表!!!");
return;
}
//判断删除的位置是否正确
if(index < 1 || index > size){
System.out.println("删除的位置不正确!!!");
return;
}
for (int i = 1; i <= index; i++) {
tmp = tmp.next;
}
if(tmp.next != null){
tmp.next.pre = tmp.pre;
tmp.pre.next = tmp.next;
}else{
//相当于删除最后一个结点
tmp.pre.next = null;
}
size--;
}
/*
* 5.2指定编号删除
*/
public void idDetleNode(int id){
Node tmp = head;
//判断链表是否为空链表
if(head.next == null){
System.out.println("空链表!!!");
return;
}
for (int i = 1; i <= size; i++) {
tmp = tmp.next;
if(tmp.getId() == id){
System.out.println("删除成功!!!");
break;
}
}
if(tmp.next != null){
tmp.pre.next = tmp.next;
tmp.next.pre = tmp.pre;
}else{
//相当于删除最后一个结点
tmp.pre.next = null;
}
size--;
}
/*
* 5.3指定姓名删除
*/
public void nameDetleNode(String name){
Node tmp = head;
//判断指定姓名是否存在
boolean ifNameExists = false;
//判断是否为空链表
if(head.next == null){
System.out.println("空链表!!!");
return;
}
//获得总结点数
int len = size;
for (int i = 1; i <= len; i++) {
tmp = tmp.next;
if(tmp.getName().equals(name)){
if(tmp.next !=null){
tmp.next.pre = tmp.pre;
tmp.pre.next = tmp.next;
}else {
tmp.pre.next = null;
}
ifNameExists = true;
size--;
}
}
if(!ifNameExists){
System.out.println("要删除的姓名不存在!!!");
}
}
/*
* 6.1根据编号进行修改
*/
public void idUpdateNode(int id,Node node){
Node tmp = head;
boolean ifIdExists = false;
//判断是否为空链表
if(head.next == null){
System.out.println("空链表!!!");
return;
}
for (int i = 1; i <= size; i++) {
tmp = tmp.next;
if(tmp.getId() == id){
//判断tmp是否为最后一个结点
if(tmp.next != null){
node.next = tmp.next;
tmp.next.pre = node;
}
tmp.pre.next = node;
node.pre = tmp.pre;
ifIdExists = true;
break;
}
}
if(!ifIdExists){
System.out.println("指定的编号不存在!!!");
}
}
/*
* 6.2根据姓名进行修改
*/
public void nameUpdateNode(String srcName,String desName){
Node tmp = head;
boolean ifNameExists = false;
//判断是否为空链表
if(head.next == null){
System.out.println("空链表!!!");
return;
}
for (int i = 1; i <= size; i++) {
tmp = tmp.next;
if(tmp.getName().equals(srcName)){
tmp.setName(desName);
ifNameExists = true;
}
}
if(!ifNameExists){
System.out.println("姓名不存在!!!");
}
}
/*
* 7.根据编号进行排序
*/
private void sortDoubleList(){
Node newHead = head.next;
for(int i = 0; i< size - 1; i++){
//前一个元素指针
Node preNode = null;
//当前处理的元素
Node curNode = newHead;
for(int j = 0; j < size - i - 1;j++){
if(curNode.getId() > curNode.next.getId()){
//交换两个结点的引用,此时curNode的指针交换后会前移,只需要更新preNode指向即可
//缓存下下个结点
Node tmpNode = curNode.next.next;
curNode.next.next = curNode;
curNode.pre = curNode.next;
//前驱结点指向nextNode
if(preNode != null){
preNode.next = curNode.next;
curNode.next.pre = preNode;
}else{
//没有前驱结点证明结点为头结点,更新头结点
newHead = curNode.next;
}
//因为需要把preNode指向原来的下个结点,所以此处复制preNode,preNode后移
preNode = curNode.next;
//curNode指向下下个结点
curNode.next = tmpNode;
//更新preNode & curNode指针
}else{
preNode = curNode;
curNode = curNode.next;
}
}
}
head.next = newHead;
}
/*
* 8.两个有序单链表合并,并且有序
*/
public static void combinNodeToNode(DoubleLikeListSample srcDoubleLink,DoubleLikeListSample desDoubleLink){
Node srcHeadNode = srcDoubleLink.getHead();
Node desHeadNode = desDoubleLink.getHead();
for (int i = 1; i <= srcDoubleLink.getSize(); i++) {
srcHeadNode = srcHeadNode.next;
}
srcHeadNode.next = desHeadNode.next;
//排序
srcDoubleLink.size = srcDoubleLink.getSize() + desDoubleLink.getSize();
srcDoubleLink.sortDoubleList();
}
/*
* 9.打印
*/
public void print(){
Node tmp = head;
for (int i = 1; i <= size; i++) {
tmp = tmp.next;
System.out.println(tmp.toString());
}
}
/*
* 10.从尾到头打印单链表
*/
public void endToStartPrint(){
//判断是否为空链表
if(head.next == null){
System.out.println("空链表");
return;
}
Node tmp = head;
//使用栈---先进后出
Stack<Node> stack = new Stack<>();
for (int i = 1; i <= size; i++) {
tmp = tmp.next;
stack.push(tmp);
}
while (stack.size() > 0) {
System.out.println(stack.pop().toString());
}
}
/*
* 11.双向链表反转
* 思想:总是以当前的结点为基准,与头结点进行链接
*/
public void reverseDoubleList(){
Node cur = head.next; //当前结点
Node next = null; //下一个结点
Node tmpHead = new Node(0,""); //前一个指针
//判断是否为空链表
if(head.next == null){
System.out.println("空链表!!!");
return;
}
while (cur != null) {
next = cur.next;
cur.next = tmpHead.next;
if(tmpHead.next != null){
tmpHead.next.pre = cur;
}
cur.pre = tmpHead;
tmpHead.next = cur;
cur = next;
}
head = tmpHead;
}
/*
* 12.查找单链表中的倒数第k个结点
* 思路:就是顺查找第size -k + 1个结点
*/
public Node findReciprocalKNode(int k){
Node node = head;
//判断k是否存在
if(k < 1 || k > size){
System.out.println("k输入不正确!!!");
return null;
}
//判断是否为空链表
if(head.next == null){
System.out.println("空链表!!!");
return null;
}
for (int i = 1; i <= size - k + 1; i++) {
node = node.next;
}
return node;
}
}