反转单链表

  1. public Node reverseLinkedList(Node head) {
  2. if (head == null || head.next == null) {
  3. return head;
  4. }
  5. Node prev = null;
  6. Node next = null;
  7. while (head != null) {
  8. next = head.next;
  9. head.next = prev;
  10. prev = head;
  11. head = next;
  12. }
  13. return prev;
  14. }

反转双链表

  1. public DoubleNode reverseDoubleLinkedList(DoubleNode head) {
  2. if (head == null || head.next == null) {
  3. return head;
  4. }
  5. DoubleNode prev = null;
  6. DoubleNode next = null;
  7. while (head != null) {
  8. next = head.next;
  9. head.next = prev;
  10. head.prev = next;
  11. prev = head;
  12. head = next;
  13. }
  14. return prev;
  15. }

在链表中删除指定值的所有节点

  1. public Node removeValue(Node head, int value) {
  2. if (head == null) {
  3. return head;
  4. }
  5. //考虑头节点开始就是需要删除的节点
  6. while (head != null && head.value == value) {
  7. head = head.next;
  8. }
  9. Node prev = null;
  10. Node curr = head;
  11. while (curr != null) {
  12. if (curr.value == value) {
  13. prev.next = curr.next;
  14. } else {
  15. prev = curr;
  16. }
  17. curr = curr.next;
  18. }
  19. return head;
  20. }

用双链表实现栈和队列

可先实现双端队列, 使用双端队列实现队列(先进先出) 使用双端队列实现栈(先进后出)

  1. //双端队列实现方法
  2. public class DoubleEndsQueue<T> {
  3. private Node<T> head;
  4. private Node<T> tail;
  5. private int size;
  6. //从头部添加
  7. public void addFromHead(T value) {
  8. Node<T> node = new Node<>(value);
  9. if (head == null) {
  10. head = node;
  11. tail = node;
  12. } else {
  13. node.next = head;
  14. head.prev = node;
  15. head = node;
  16. }
  17. size++;
  18. }
  19. //从底部添加
  20. public void addFromBottom(T value) {
  21. Node<T> node = new Node<>(value);
  22. if (tail == null) {
  23. tail = node;
  24. head = tail;
  25. } else {
  26. tail.next = node;
  27. node.prev = tail;
  28. tail = node;
  29. }
  30. size++;
  31. }
  32. //从头部获取
  33. public T popFromHead() {
  34. if (head == null) {
  35. return null;
  36. }
  37. Node<T> result = head;
  38. if (head == tail) {
  39. head = null;
  40. tail = null;
  41. } else {
  42. head = head.next;
  43. head.prev = null;
  44. result.next = null;
  45. }
  46. size--;
  47. return result.value;
  48. }
  49. //从底部获取
  50. public T popFromBottom() {
  51. if (tail == null) {
  52. return null;
  53. }
  54. Node<T> result = tail;
  55. if (head == tail) {
  56. head = null;
  57. tail = null;
  58. } else {
  59. tail = tail.prev;
  60. tail.next = null;
  61. result.prev = null;
  62. }
  63. size--;
  64. return result.value;
  65. }
  66. public int getSize() {
  67. return size;
  68. }
  69. public boolean isEmpty() {
  70. return size == 0;
  71. }
  72. }

用环形数组实现栈和队列

技巧:在数据结构中增加一个size变量,如此可免去判断读写子指针相交问题

  1. //队列的实现
  2. public static class RingArrayQueue<T> {
  3. private Object[] arr;
  4. private int limit;
  5. private int size;
  6. private int readIdx = 0;
  7. private int writeIdx = 0;
  8. public RingArrayQueue(int maxSize) {
  9. if (maxSize < 1) {
  10. throw new InvalidParameterException("最大值需大于0,maxSize: " + maxSize);
  11. }
  12. this.limit = maxSize;
  13. this.arr = new Object[maxSize];
  14. }
  15. public void put(T value) {
  16. if (size == limit) {
  17. throw new RuntimeException("容量满了");
  18. }
  19. arr[writeIdx++] = value;
  20. writeIdx = writeIdx == limit ? 0 : writeIdx;
  21. size++;
  22. }
  23. public T pop() {
  24. if (size == 0) {
  25. throw new RuntimeException("没有数据啦");
  26. }
  27. Object result = arr[readIdx++];
  28. readIdx = readIdx == limit ? 0 : readIdx;
  29. size--;
  30. return (T) result;
  31. }
  32. public int getSize() {
  33. return size;
  34. }
  35. public boolean isEmpty() {
  36. return size == 0;
  37. }
  38. }
  1. //栈的实现
  2. public class MyStack<T> {
  3. private Object[] arr;
  4. private int limit;
  5. private int size;
  6. private int writReadIdx;
  7. public MyStack(int limit) {
  8. if (limit < 1) {
  9. throw new RuntimeException("limit需大于0");
  10. }
  11. this.limit = limit;
  12. arr = new Object[limit];
  13. }
  14. public void push(T value) {
  15. if (size == limit) {
  16. throw new RuntimeException("容量满了");
  17. }
  18. arr[writReadIdx++] = value;
  19. writReadIdx = writReadIdx == limit ? 0 : writReadIdx;
  20. size++;
  21. }
  22. public T pop() {
  23. if (size == 0) {
  24. throw new RuntimeException("没有值了");
  25. }
  26. writReadIdx = writReadIdx - 1 < 0 ? limit - 1 : --writReadIdx;
  27. size--;
  28. return (T) arr[writReadIdx];
  29. }
  30. public int size() {
  31. return size;
  32. }
  33. public boolean isEmpty() {
  34. return size == 0;
  35. }
  36. }

实现有getMin功能的栈

利用两个栈,一个栈记录数据,另一个栈同步记录当前最小的值

  1. public class GetMinStack {
  2. private Stack<Integer> data;
  3. private Stack<Integer> min;
  4. public GetMinStack() {
  5. this.data = new Stack<>();
  6. this.min = new Stack<>();
  7. }
  8. public void push(int value) {
  9. if (min.isEmpty()) {
  10. min.push(value);
  11. } else {
  12. Integer preMin = min.peek();
  13. min.push(Math.min(preMin, value));
  14. }
  15. data.push(value);
  16. }
  17. public int pop() {
  18. min.pop();
  19. return data.pop();
  20. }
  21. public int getMin() {
  22. return min.peek();
  23. }
  24. }

两个栈实现队列

弹出栈为空的时候才从写入栈去导入 写入栈导入弹出栈时需一次性导完

  1. public class TwoStackQueue<T> {
  2. private Stack<T> push;
  3. private Stack<T> pop;
  4. public TwoStackQueue() {
  5. this.push = new Stack<>();
  6. this.pop = new Stack<>();
  7. }
  8. public void push(T value) {
  9. push.push(value);
  10. }
  11. public T poll() {
  12. pushToPop();
  13. return pop.pop();
  14. }
  15. private void pushToPop() {
  16. if (pop.isEmpty() && !push.isEmpty()) {
  17. while (!push.isEmpty()) {
  18. pop.push(push.pop());
  19. }
  20. }
  21. }
  22. public T peek() {
  23. pushToPop();
  24. return pop.peek();
  25. }
  26. public boolean isEmpty() {
  27. return pop.isEmpty() && pop.isEmpty();
  28. }
  29. }

两个队列实现栈

弹出数据的时候,将主队列数据移动到辅助队列,再将主队列和辅助队列应用交换

  1. public static class TwoQueueStack<T> {
  2. public Queue<T> queue;
  3. public Queue<T> help;
  4. public TwoQueueStack() {
  5. queue = new LinkedList<>();
  6. help = new LinkedList<>();
  7. }
  8. public void push(T value) {
  9. queue.offer(value);
  10. }
  11. public T poll() {
  12. while (queue.size() > 1) {
  13. help.offer(queue.poll());
  14. }
  15. T ans = queue.poll();
  16. Queue<T> tmp = queue;
  17. queue = help;
  18. help = tmp;
  19. return ans;
  20. }
  21. public T peek() {
  22. while (queue.size() > 1) {
  23. help.offer(queue.poll());
  24. }
  25. T ans = queue.poll();
  26. help.offer(ans);
  27. Queue<T> tmp = queue;
  28. queue = help;
  29. help = tmp;
  30. return ans;
  31. }
  32. public boolean isEmpty() {
  33. return queue.isEmpty();
  34. }
  35. }