首先定义节点封装类
/**
*
* @author c332030
* @Description 节点封装类
* @date 2019-02-26
* @version 1.0
*/
class Node {
Node pre= null;
Node next = null;
int data;
Node(int data) {
this.data = data;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node node = (Node) o;
return data == node.data;
}
@Override
public int hashCode() {
return Objects.hash(pre, next, data);
}
@Override
public String toString() {
return "Node{" +
"data=" + data +
'}';
}
}
然后定义链表封装类
/**
*
* @author c332030
* @Description 链表封装类
* @date 2019-02-26
* @version 1.0
*/
class Linked {
Node start = null;
Node end = null;
Linked(Node start, Node end) {
this.start = start;
this.end = end;
}
void print() {
Node node = start;
// while(null != node) {
// System.out.print(node.pre);
// System.out.print(" - ");
// System.out.print(node);
// System.out.print(" - ");
// System.out.print(node.next);
// System.out.println();
// node = node.next;
// }
}
void print2() {
Node node = start;
while(null != node) {
System.out.print(node.data);
System.out.print(" ");
node = node.next;
}
System.out.println();
}
@Override
public String toString() {
return "Linked{start= " + start + ",end= " + end + "}";
}
}
介绍几个辅助的方法
/**
*
* @author c332030
* @Description 获取链表头结点
* @date 2019-02-26
* @version 1.0
*/
Node getStart(Node node) {
if(null == node) {
return null;
}
while(node.pre != null) {
node = node.pre;
}
return node;
}
/**
*
* @author c332030
* @Description 获取链表尾节点
* @date 2019-02-26
* @version 1.0
*/
Node getEnd(Node node) {
if(null == node) {
return null;
}
while(node.next != null) {
node = node.next;
}
return node;
}
交换节点位置的方法
/**
*
* @author c332030
* @Description 节点位置交换
* @date 2019-02-26
* @version 1.0
*/
void exchangeNode(
Linked linked0, // 更新链表的头节点和尾节点
Linked linked, // 更新当前排序的 start 和 end 节点
Node point1, Node point2 // 要交换的节点
) {
if(null == point1
|| null == point2
|| point1 == point2
) {
return;
}
System.out.println("exchangeNode point1= " + point1 + " point2= " + point2);
if(point1 == linked.start) { // point2 为第一个时,更新头结点
System.out.println("exchangeNode start= " + linked.start + ",point1= " + point2);
linked.start = point2;
}
if(point2 == linked.end) { // point2 为最后一个时,更新尾节点
System.out.println("exchangeNode end= " + linked.end + ",point2= " + point1);
linked.end = point1;
}
if(null != point1.pre) {
point1.pre.next = point2;
}
if(null != point2.pre) {
point2.pre.next = point1;
}
Node tmpPre = point1.pre;
point1.pre = point2.pre;
point2.pre = tmpPre;
if(null != point1.next) {
point1.next.pre = point2;
}
if(null != point2.next ) {
point2.next.pre = point1;
}
Node tmpNext = point1.next;
point1.next = point2.next;
point2.next = tmpNext;
if(null == linked.start.pre) { // 更新链表头结点
linked0.start = linked.start;
}
}
然后重点,快速排序的方法
/**
*
* @author c332030
* @Description 快速排序
* @date 2019-02-26
* @version 1.0
*/
void sort(Linked linked0, Linked linked) {
if(linked.start == linked.end
|| null == linked.start
|| null == linked.end
) {
return;
}
final Node middle = linked.start;
Node point1 = linked.start;
Node point2 = linked.end;
while(point1 != point2) {
// System.out.println("point1= " + point1 + " point2= " + point2);
while(point1 != point2
&& middle.data < point2.data
&& point2 != linked.start
) {
System.out.println(linked
+ "data= " + middle.data
+ " point2= " + point2
+ " point2.pre=" + point2.pre
);
point2 = point2.pre; // 往前移
}
while(point1 != point2
&& middle.data >= point1.data
&& point1 != linked.end
) { // 等于时后移
System.out.println(linked
+ "data= " + middle.data
+ " point1= " + point1
+ " point1.next= " + point1.next
);
point1 = point1.next; // 往后移
}
if(point1 == point2) {
break;
}
exchangeNode(linked0, linked, point1, point2);
Node tmpNode = point1;
point1 = point2;
point2 = tmpNode;
}
System.out.println("chang to start: " + point1);
exchangeNode(linked0, linked, linked.start, point1);
linked.print();
System.out.print("middle.pre= " + middle.pre);
System.out.print(", middle= " + middle);
System.out.print(", middle.next= " + middle.next);
System.out.println();
new Linked(getStart(middle), null).print2(); // 打印整个链表
linked.print2();
// try {
// Thread.sleep(500);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
if(linked.start != middle
&& null != middle.pre
) {
System.out.println("has left");
sort(linked0, new Linked(linked.start, middle.pre));
}
if(linked.end != middle
&& null != middle.next
) {
System.out.println("has right");
sort(linked0, new Linked(middle.next, linked.end));
}
}
然后测试代码:
/**
* @author c332030
* @Description 测试方法
* @date 2019-02-26
* @version 1.0
*/
void sortStart() {
int[] arr = {5, 9, 6, 0, 3, 4, 7, 2, 1, 8};
Node node = new Node(arr[0]);
Node start = node;
for(int i = 1; i < arr.length; i++) { // 新建测试双向链表
Node tmpNode = new Node(arr[i]);
node.next = tmpNode;
tmpNode.pre = node;
node = tmpNode;
}
Linked linked = new Linked(start, getEnd(start));
sort(linked, linked);
System.out.println("sorted");
linked.print();
linked.print2();
}
输出结果:
如果不想用递归实现的话,新建一个封装类,类的属性就是 sort 方法的参数,然后新建一个队列,第一次及每次需要递归的时候就把参数压入队列,sort方法的逻辑用while循环包括起来,while里面出队列并执行逻辑,循环结束条件就是队列为空。
懒癌发作,就不实现了,原理就是自己模仿递归的流程。