反转单链表,双链表
import java.util.ArrayList;
import java.util.List;
public class ReverseList {
public static class Node{
public int value;
public Node next;
public Node(int data){
value = data;
}
}
public static class DoubleNode{
public int value;
public DoubleNode last;
public DoubleNode next;
public DoubleNode(int data){
value = data;
}
}
// 利用双指针,反转单链表
// head a - > b - > c - > d - > e - > null
public static Node reverseLinkedList(Node head){
Node pre = null;
Node next = null;
while(null != head){
next = head.next;
head.next = pre;
pre = head;
head = next;
}
return pre;
}
// 反转双向链表
public static DoubleNode reverseDoubleList(DoubleNode head){
DoubleNode pre = null;
DoubleNode next = null;
while(head != null){
next = head.next;
head.next = pre;
head.last = next;
pre = head;
head = next;
}
return pre;
}
public static Node testReverseLinkedList(Node head){
if(null == head){
return null;
}
ArrayList<Node> list = new ArrayList<>();
while(head != null){
list.add(head);
head = head.next;
}
list.get(0).next = null;
int N = list.size();
for (int i = 1; i < N; i++) {
list.get(i).next = list.get(i-1);
}
return list.get(N-1);
}
public static Node generateRandomLinkedList(int len, int value){
int size = (int)(Math.random() * (len+1));
if(size == 0){
return null;
}
size--;
Node head = new Node((int)(Math.random())*(value+1));
Node pre = head;
while(size != 0){
Node cur = new Node((int)(Math.random())*(value+1));
pre.next = cur;
pre = cur;
size--;
}
return head;
}
public static List<Integer> getLinkedListOriginOrder(Node head){
List<Integer> ans = new ArrayList<>();
while(head != null){
ans.add(head.value);
head = head.next;
}
return ans;
}
public static boolean checkLinkedListReverse(List<Integer> origin, Node head){
for (int i = origin.size()-1; i >= 0 ; i--) {
if(!origin.get(i).equals(head.value)){
return false;
}
head = head.next;
}
return true;
}
public static void main(String[] args) {
int len = 50;
int value = 100;
int testTime = 100000;
System.out.println("test Begin!!");
for (int i = 0; i < testTime; i++) {
Node node1 = generateRandomLinkedList(len,value);
List<Integer> list1 = getLinkedListOriginOrder(node1);
node1 = reverseLinkedList(node1);
if(!checkLinkedListReverse(list1,node1)){
System.out.println("Oops1!");
}
}
System.out.println("test end!!");
}
// 删除链表中值等于num的节点
public static Node removeValue(Node head, int num){
while(null != head){
// 来到第一个不需要删的位置
if(head.value != num){
break;
}
head = head.next;
}
Node pre = head;
Node cur = head;
while(cur != null){
if(cur.value == num){
pre.next = cur.next;
}else{
pre = cur;
}
cur = cur.next;
}
return head;
}
}
队列和栈是逻辑上的概念
数组和链表都能实现队列和栈。
双端链表实现队列
public class DoubleEndsQueueToStackAndQueue {
public static class Node<T>{
public T value;
public Node<T> last;
public Node<T> next;
public Node(T data){
value = data;
}
}
// 双端队列
public static class DoubleEndsQueue<T>{
public Node<T> head; // 头指针
public Node<T> tail; // 尾指针
// 从头部加
public void addFromHead(T value){
Node<T> cur = new Node(value);
if(head == null){
head = cur;
tail = cur;
}else{
head.last = cur;
cur.next = head;
head = cur;
}
}
// 从尾部加
public void addFromBottom(T value){
Node<T> cur = new Node(value);
if(tail == null){
head = cur;
tail = cur;
}else{
tail.next = cur;
cur.last = tail;
tail = cur;
}
}
// 从头部弹出来
public T popFromHead(){
if(head == null){
return null;
}
Node<T> cur = head;
if(head == tail){
tail = null;
head = null;
}else{
head = head.next;
cur.next = null;
head.last = null;
}
return cur.value;
}
// 从尾部弹出来
public T popFromTail(){
if(head == null){
return null;
}
Node<T> cur = tail;
if(head == tail){
tail = null;
head = null;
}else{
tail = tail.last;
tail.next = null;
cur.last = null;
}
return cur.value;
}
}
public static void main(String[] args) {
}
}
数组实现队列
public class RingArray {
public static class MyQueue{
private int[] arr;
private int pushi;
private int polli;
private int size; // 已加入到队列中的个数
private final int limit; // 队列最多能装多少个
public MyQueue(int limit){
arr = new int[limit];
pushi = 0;
polli = 0;
size = 0;
this.limit = limit;
}
public void push(int value){
if(size == limit){
throw new RuntimeException("栈满了,不能再加了");
}
size++;
arr[pushi] = value;
pushi = nextIndex(pushi);
}
public int pop(int value){
if(size == 0){
throw new RuntimeException("栈空了,不能再拿了");
}
size--;
int cur = arr[polli];
polli = nextIndex(polli);
return cur;
}
public boolean isEmpty(){
return size == 0 ? true : false;
}
// 如果现在的下标值是i,返回下一个位置
public int nextIndex(int i){
// 如果没到底,位置就加1。 如果位置到底,就返回0
return i < limit - 1 ? i+1 : 0;
}
}
}
实现一个特殊的栈,在实现基本功能的基础上,再实现返回栈中最小元素的功能
- pop,push,getMin操作的时间复杂度都是O(1)
- 设计的栈类型可以使用现成的栈结构
题目: 如何用栈结构实现队列结构
import java.util.Stack;
public class TwoStacksImplementQueue {
public static class TwoStacksQueue{
public Stack<Integer> stackPush;
public Stack<Integer> stackPop;
public TwoStacksQueue(){
stackPush = new Stack<Integer>();
stackPop = new Stack<Integer>();
}
// 从push栈往pop栈倒入数据
private void pushToPop(){
if(stackPop.empty()) { // 只有pop栈不为空
while (!stackPush.isEmpty()) {
stackPop.push(stackPush.pop());
}
}
}
public void add(int pushInt){
stackPush.push(pushInt);
pushToPop();
}
public int poll(){
if(stackPush.empty() && stackPop.empty()){
throw new RuntimeException("Queue is empty");
}
pushToPop();
return stackPop.pop();
}
public int peek(){
if(stackPush.isEmpty() && stackPop.isEmpty()){
throw new RuntimeException("Queue is empty");
}
pushToPop();
return stackPop.peek();
}
}
public static void main(String[] args) {
}
}
题目: 如何用队列结构实现栈结构
package datastructure.trainingcamp.Code03;
import java.util.LinkedList;
import java.util.Queue;
public class TwoQueueImplementStack {
public static class TwoQueueStack<T>{
public Queue<T> queue;
public Queue<T> help;
public TwoQueueStack(){
queue = new LinkedList<>();
help = new LinkedList<>();
}
public void push(T value){
queue.offer(value);
}
public T poll(){
while(queue.size() > 1){
help.offer(queue.poll());
}
T ans = queue.poll();
Queue<T> tmp = queue;
queue = help;
help = tmp;
return ans;
}
public T peek(){
while(queue.size() > 1){
help.offer(queue.poll());
}
T ans = queue.poll();
help.offer(ans);
Queue<T> tmp = queue;
queue = help;
help = tmp;
return ans;
}
}
public static void main(String[] args) {
}
}
任何递归都可以改成非递归
红黑树,avl,sb树,跳表都能实现有序表。