一些基础的数据结构

155 阅读2分钟

翻转、生成单向和双向链表

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; // 默认为null
   public DoubleNode next; // 默认为null

   public DoubleNode(int data) {
      value = data;
   }
}

//  head
//   a    ->   b    ->  c  ->  null
//   c    ->   b    ->  a  ->  null
public static Node reverseLinkedList(Node head) {
   Node pre = null;
   Node next = null;
   while (head != null) {
      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 (head == null) {
      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 DoubleNode testReverseDoubleList(DoubleNode head) {
   if (head == null) {
      return null;
   }
   ArrayList<DoubleNode> list = new ArrayList<>();
   while (head != null) {
      list.add(head);
      head = head.next;
   }
   list.get(0).next = null;
   DoubleNode pre = list.get(0);
   int N = list.size();
   for (int i = 1; i < N; i++) {
      DoubleNode cur = list.get(i);
      cur.last = null;
      cur.next = pre;
      pre.last = cur;
      pre = cur;
   }
   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)));
   // pre变量防止head丢失
   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 DoubleNode generateRandomDoubleList(int len, int value) {
   int size = (int) (Math.random() * (len + 1));
   if (size == 0) {
      return null;
   }
   size--;
   DoubleNode head = new DoubleNode((int) (Math.random() * (value + 1)));
   DoubleNode pre = head;
   while (size != 0) {
      DoubleNode cur = new DoubleNode((int) (Math.random() * (value + 1)));
      pre.next = cur;
      // 就比单链表多了这一步
      cur.last = pre;
      pre = cur;
      size--;
   }
   return head;
}

删除链表中的指定的值

leetcode.com/problems/re…

public static class Node {
   public int value;
   public Node next;

   public Node(int data) {
      this.value = data;
   }
}

// head = removeValue(head, 2);
public static Node removeValue(Node head, int num) {
   // head来到第一个不需要删的位置
   while (head != null) {
      if (head.value != num) {
         break;
      }
      head = head.next;
   }
   // 1 ) head == null
   // 2 ) head != null
   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 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<T>(value);
      if (head == null) {
         head = cur;
         tail = cur;
      } else {
         cur.next = head;
         head.last = cur;
         head = cur;
      }
   }
   public void addFromBottom(T value) {
      Node<T> cur = new Node<T>(value);
      if (head == null) {
         head = cur;
         tail = cur;
      } else {
         cur.last = tail;
         tail.next = cur;
         tail = cur;
      }
   }
   public T popFromHead() {
      if(head == null) {
         return null;
      }
      Node<T> cur = head;
      if(head == tail) {
         head = null;
         tail = null;
      } else {
         head = head.next;
         cur.next = null;
         head.last = null;
      }
      return cur.value;
   }
   public T popFromBottom() {
      if (head == null) {
         return null;
      }
      Node<T> cur = tail;
      if (head == tail) {
         head = null;
         tail = null;
      } else {
         tail = tail.last;
         tail.next = null;
         cur.last = null;
      }
      return cur.value;
   }
   public boolean isEmpty() {
      return head == null;
   }
}

public static class MyStack<T> {
   private DoubleEndsQueue<T> queue;

   public MyStack() {
      queue = new DoubleEndsQueue<T>();
   }

   public void push(T value) {
      queue.addFromHead(value);
   }

   public T pop() {
      return queue.popFromHead();
   }

   public boolean isEmpty() {
      return queue.isEmpty();
   }

}

public static class MyQueue<T> {
   private DoubleEndsQueue<T> queue;

   public MyQueue() {
      queue = new DoubleEndsQueue<T>();
   }

   public void push(T value) {
      queue.addFromHead(value);
   }

   public T poll() {
      return queue.popFromBottom();
   }

   public boolean isEmpty() {
      return queue.isEmpty();
   }

}

public static boolean isEqual(Integer o1, Integer o2) {
   if (o1 == null && o2 != null) {
      return false;
   }
   if (o1 != null && o2 == null) {
      return false;
   }
   if (o1 == null && o2 == null) {
      return true;
   }
   return o1.equals(o2);
}

public static void main(String[] args) {
   int oneTestDataNum = 100;
   int value = 10000;
   int testTimes = 100000;
   for (int i = 0; i < testTimes; i++) {
      MyStack<Integer> myStack = new MyStack<>();
      MyQueue<Integer> myQueue = new MyQueue<>();
      Stack<Integer> stack = new Stack<>();
      Queue<Integer> queue = new LinkedList<>();
      for (int j = 0; j < oneTestDataNum; j++) {
         int nums = (int) (Math.random() * value);
         if (stack.isEmpty()) {
            myStack.push(nums);
            stack.push(nums);
         } else {
            if (Math.random() < 0.5) {
               myStack.push(nums);
               stack.push(nums);
            } else {
               if (!isEqual(myStack.pop(), stack.pop())) {
                  System.out.println("oops!");
               }
            }
         }
         int numq = (int) (Math.random() * value);
         if (stack.isEmpty()) {
            myQueue.push(numq);
            queue.offer(numq);
         } else {
            if (Math.random() < 0.5) {
               myQueue.push(numq);
               queue.offer(numq);
            } else {
               if (!isEqual(myQueue.poll(), queue.poll())) {
                  System.out.println("oops!");
               }
            }
         }
      }
   }
   System.out.println("finish!");
}

数组实现栈

public static class MyQueue {
    private int[] arr;
    private int pushi;// end
    private int polli;// begin
    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("no");
        }
        size++;
        arr[pushi] = value;
        pushi = nextIndex(pushi);
    }


    public int pop() {
        if(size == 0) {
            throw new RuntimeException("no");
        }
        size--;
        int ans = arr[polli];
        polli = nextIndex(polli);
        return ans;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public int size() {
        return size;
    }

    // 如果现在的下标是i,返回下一个位置
    private int nextIndex(int i) {
        return i < limit - 1 ? i + 1 : 0;
    }

}

public static void main(String[] args) {
    int value = 1000, testTime = 1000000, limit = 10;
    MyQueue myQueue = new MyQueue(limit);
    Queue<Integer> queue = new LinkedList<>();
    for (int i = 0; i < testTime; i++) {
        int num = (int) (Math.random() * (value + 1));
        if (queue.isEmpty()) {
            queue.offer(num);
            myQueue.push(num);
        } else {
            // 可能会加入队列,也可能会出队列,出队列时进行对比
            if (Math.random() < 0.5 && myQueue.size() < limit) {
                queue.offer(num);
                myQueue.push(num);
            } else {
                // equals是包装类Integer的方法,可以和int类型比较数值是否相等
                if (!queue.poll().equals(myQueue.pop())) {
                    System.out.println("no");
                }
            }
        }
    }
    System.out.println("test end");
}

最小栈

实现一个栈结构,可以用O(1)的复杂度得出当前所有数据中的最小值

public static class MyStack1 {
   private Stack<Integer> stackData;
   private Stack<Integer> stackMin;

   public MyStack1() {
      this.stackData = new Stack<Integer>();
      this.stackMin = new Stack<Integer>();
   }

   public void push(int newNum) {
      if (this.stackMin.isEmpty()) {
         this.stackMin.push(newNum);
      } else if (newNum <= this.getmin()) {
         this.stackMin.push(newNum);
      }
      this.stackData.push(newNum);
   }

   public int pop() {
      if (this.stackData.isEmpty()) {
         throw new RuntimeException("Your stack is empty.");
      }
      int value = this.stackData.pop();
      if (value == this.getmin()) {
         this.stackMin.pop();
      }
      return value;
   }

   public int getmin() {
      if (this.stackMin.isEmpty()) {
         throw new RuntimeException("Your stack is empty.");
      }
      return this.stackMin.peek();
   }
}

栈实现队列

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()) {
         while (!stackPush.empty()) {
            stackPop.push(stackPush.pop());
         }
      }
   }

   public void add(int pushInt) {
      stackPush.push(pushInt);
      pushToPop();
   }

   public int poll() {
      if (stackPop.empty() && stackPush.empty()) {
         throw new RuntimeException("Queue is empty!");
      }
      pushToPop();
      return stackPop.pop();
   }

   public int peek() {
      if (stackPop.empty() && stackPush.empty()) {
         throw new RuntimeException("Queue is empty!");
      }
      pushToPop();
      return stackPop.peek();
   }
}

队列实现栈

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 boolean isEmpty() {
      return queue.isEmpty();
   }
}