ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

数据结构学习第二天<反转链表><链表删除节点><栈和队列><两个栈实现队列><两个队列实现栈><递归求最大值><哈希表>

2022-06-09 10:02:52  阅读:82  来源: 互联网

标签:head 队列 System 链表 int println 数据结构 public out


反转链表

package Demo02;
​
import java.util.ArrayList;
import java.util.List;
​
public class Code01_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;
        }
    }
​
    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);
    }
​
    // for test
    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;
    }
​
    // for test
    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;
    }
​
    // for test
    public static List<Integer> getLinkedListOriginOrder(Node head) {
        List<Integer> ans = new ArrayList<>();
        while (head != null) {
            ans.add(head.value);
            head = head.next;
        }
        return ans;
    }
​
    // for test
    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;
    }
​
    // for test
    public static List<Integer> getDoubleListOriginOrder(DoubleNode head) {
        List<Integer> ans = new ArrayList<>();
        while (head != null) {
            ans.add(head.value);
            head = head.next;
        }
        return ans;
    }
​
    // for test
    public static boolean checkDoubleListReverse(List<Integer> origin, DoubleNode head) {
        DoubleNode end = null;
        for (int i = origin.size() - 1; i >= 0; i--) {
            if (!origin.get(i).equals(head.value)) {
                return false;
            }
            end = head;
            head = head.next;
        }
        for (int i = 0; i < origin.size(); i++) {
            if (!origin.get(i).equals(end.value)) {
                return false;
            }
            end = end.last;
        }
        return true;
    }
​
​
    public static void f(Node head) {
        head = head.next;
    }
​
    // for test
    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!");
            }
​
            Node node2 = generateRandomLinkedList(len, value);
            List<Integer> list2 = getLinkedListOriginOrder(node2);
            node2 = testReverseLinkedList(node2);
            if (!checkLinkedListReverse(list2, node2)) {
                System.out.println("Oops2!");
            }
​
            DoubleNode node3 = generateRandomDoubleList(len, value);
            List<Integer> list3 = getDoubleListOriginOrder(node3);
            node3 = reverseDoubleList(node3);
            if (!checkDoubleListReverse(list3, node3)) {
                System.out.println("Oops3!");
            }
​
            DoubleNode node4 = generateRandomDoubleList(len, value);
            List<Integer> list4 = getDoubleListOriginOrder(node4);
            node4 = reverseDoubleList(node4);
            if (!checkDoubleListReverse(list4, node4)) {
                System.out.println("Oops4!");
            }
​
        }
        System.out.println("test finish!");
​
    }
​
}

 

链表删除节点

单向链表删除头结点后,head指向第二个时,即便头结点没有断连(只有1指向2,没有2指向1,2顺着能找到3,4...但找不到1),内存也会释放,C++不行(必须调用释放函数),双向链表则不会(2有指向1,能找到1)

package Demo02;
​
public class Code02_DeleteGivenValue {
    public static class Node {
        public int value;
        public Node next;
​
        public Node(int data) {
            this.value = data;
        }
    }
​
    public static Node removeValue(Node head, int num) {
        while (head != null) {
            if (head.value != num) {
                break;
            }
            head = head.next;
        }
        // head来到 第一个不需要删的位置
        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;
    }
}

 

栈和队列

栈:先进后出

队列:先进先出

 

双向链表实现

package Demo02;
​
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
​
public class Code03_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<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!");
    }
}

 

数组实现(固定大小)

栈容易实现

package Demo02;
​
public class Code04_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() {
            if (size == 0) {
                throw new RuntimeException("栈空了,不能再拿了");
            }
            size--;
            int ans = arr[polli];
            polli = nextIndex(polli);
            return ans;
        }
​
        public boolean isEmpty() {
            return size == 0;
        }
​
        // 如果现在的下标是i,返回下一个位置
        private int nextIndex(int i) {
            return i < limit - 1 ? i + 1 : 0;
        }
​
    }
​
}

 

在实现基本功能基础上再实现返回栈中最小元素

pop push getMin时间复杂度都是O(1)

package Demo02;
​
import java.util.Stack;
​
public class Code05_GetMinStack {
    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 MyStack2 {
        private Stack<Integer> stackData;
        private Stack<Integer> stackMin;
​
        public MyStack2() {
            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);//最小栈压入当前数
            } else {
                int newMin = this.stackMin.peek();//否则最小栈重复压入栈顶
                this.stackMin.push(newMin);
            }
            this.stackData.push(newNum);//Data栈正常压入
        }
​
        public int pop() {
            if (this.stackData.isEmpty()) {
                throw new RuntimeException("Your stack is empty.");
            }
            this.stackMin.pop();//弹出最小数
            return this.stackData.pop();//同步弹出Data栈顶
        }
​
        public int getmin() {
            if (this.stackMin.isEmpty()) {
                throw new RuntimeException("Your stack is empty.");
            }
            return this.stackMin.peek();
        }
    }
​
    public static void main(String[] args) {
        MyStack1 stack1 = new MyStack1();
        stack1.push(3);
        System.out.println(stack1.getmin());
        stack1.push(4);
        System.out.println(stack1.getmin());
        stack1.push(1);
        System.out.println(stack1.getmin());
        System.out.println(stack1.pop());
        System.out.println(stack1.getmin());
​
        System.out.println("=============");
​
        MyStack1 stack2 = new MyStack1();
        stack2.push(3);
        System.out.println(stack2.getmin());
        stack2.push(4);
        System.out.println(stack2.getmin());
        stack2.push(1);
        System.out.println(stack2.getmin());
        System.out.println(stack2.pop());
        System.out.println(stack2.getmin());
    }
}

 

两个栈实现队列

package Demo02;
​
import java.util.Stack;
​
public class Code06_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()) {//原则1 必须POP栈为空的时候
                while (!stackPush.empty()) {//原则2 Push栈一定要倒空才能停
                    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 void main(String[] args) {
        TwoStacksQueue test = new TwoStacksQueue();
        test.add(1);
        test.add(2);
        test.add(3);
        System.out.println(test.peek());
        System.out.println(test.poll());
        System.out.println(test.peek());
        System.out.println(test.poll());
        System.out.println(test.peek());
        System.out.println(test.poll());
    }
}

 

两个队列实现栈

package Demo02;
​
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
​
public class Code07_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 boolean isEmpty() {
            return queue.isEmpty();
        }
​
    }
​
    public static void main(String[] args) {
        System.out.println("test begin");
        TwoQueueStack<Integer> myStack = new TwoQueueStack<>();
        Stack<Integer> test = new Stack<>();
        int testTime = 1000000;
        int max = 1000000;
        for (int i = 0; i < testTime; i++) {
            if (myStack.isEmpty()) {
                if (!test.isEmpty()) {
                    System.out.println("Oops");
                }
                int num = (int) (Math.random() * max);
                myStack.push(num);
                test.push(num);
            } else {
                if (Math.random() < 0.25) {
                    int num = (int) (Math.random() * max);
                    myStack.push(num);
                    test.push(num);
                } else if (Math.random() < 0.5) {
                    if (!myStack.peek().equals(test.peek())) {
                        System.out.println("Oops");
                    }
                } else if (Math.random() < 0.75) {
                    if (!myStack.poll().equals(test.pop())) {
                        System.out.println("Oops");
                    }
                } else {
                    if (myStack.isEmpty() != test.isEmpty()) {
                        System.out.println("Oops");
                    }
                }
            }
        }
​
        System.out.println("test finish!");
​
    }
}

 

递归求最大值

复杂度:T(N)=a*T(N/b)+O(N^d)

a子函数个数 b几分 d剩下行为复杂度因子

1.log b a >d O(N^log b a)

2.log b a <d O(N^d) 常见a=b O(1)

3.log b a =d O(N^d *log N)

package Demo02;
​
public class Code08_GetMax {
    // 求arr中的最大值
    public static int getMax(int[] arr) {
        return process(arr, 0, arr.length - 1);
    }
​
    // arr[L..R]范围上求最大值  L ... R   N
    public static int process(int[] arr, int L, int R) {
        if (L == R) { // arr[L..R]范围上只有一个数,直接返回,base case
            return arr[L];
        }
        int mid = L + ((R - L) >> 1); // 中点    1
        int leftMax = process(arr, L, mid);
        int rightMax = process(arr, mid + 1, R);
        return Math.max(leftMax, rightMax);
    }
}

 

哈希表

package Demo02;
​
import java.util.HashMap;
import java.util.HashSet;
import java.util.TreeMap;
​
public class HashMapAndSortedMap {
​
        public static class Node{
            public int value;
            public Node(int v) {
                value = v;
            }
        }
​
        public static void main(String[] args) {
            // UnSortedMap C++里的哈希表
            HashMap<Integer, String> map = new HashMap<>();//K-V
            map.put(1000000, "我是1000000");
            map.put(2, "我是2");
            map.put(3, "我是3");
            map.put(4, "我是4");
            map.put(5, "我是5");
            map.put(6, "我是6");
            map.put(1000000, "我是1000001");
​
            System.out.println(map.containsKey(1));//有无加入1的记录
            System.out.println(map.containsKey(10));
​
            System.out.println(map.get(4));//查Value
            System.out.println(map.get(10));//无记录返回null
​
            map.put(4, "他是4");//更新V
            System.out.println(map.get(4));
​
            map.remove(4);//除去
            System.out.println(map.get(4));//null
​
​
​
            //       key
            HashSet<String> set = new HashSet<>();
            set.add("abc");
            set.contains("abc");//是否存在
            set.remove("abc");
​
            // 哈希表,增、删、改、查,在使用时,复杂度O(1)
​
​
            System.out.println("=====================");
​
​
            int a = 100000;
            int b = 100000;
            System.out.println(a == b);
​
            Integer c = 100000;
            Integer d = 100000;
            System.out.println(c.equals(d));//==引用传递 equal比较值
​
            Integer e = 127;  //  - 128  ~  127 此范围内是值传递
            Integer f = 127;
            System.out.println(e == f);
​
            //哈西表里一律值传递
​
            HashMap<Node, String> map2 = new HashMap<>();
            Node node1 = new Node(1);
            Node node2 = node1;
            map2.put(node1, "我是node1");
            map2.put(node2, "我是node1");
            System.out.println(map2.size());//1  非基础类型K 引用传递
​
            System.out.println("======================");
            //有序表(按序组织)
            TreeMap<Integer, String> treeMap = new TreeMap<>();
​
            treeMap.put(3, "我是3");
            treeMap.put(4, "我是4");
            treeMap.put(8, "我是8");
            treeMap.put(5, "我是5");
            treeMap.put(7, "我是7");
            treeMap.put(1, "我是1");
            treeMap.put(2, "我是2");
​
            System.out.println(treeMap.containsKey(1));
            System.out.println(treeMap.containsKey(10));
​
            System.out.println(treeMap.get(4));
            System.out.println(treeMap.get(10));
​
            treeMap.put(4, "他是4");
            System.out.println(treeMap.get(4));
​
            treeMap.remove(4);
            System.out.println(treeMap.get(4));
​
            System.out.println(treeMap.firstKey());//最小的K
            System.out.println(treeMap.lastKey());
            // <= 4
            System.out.println(treeMap.floorKey(4));//<=4 离4最近的K
            // >= 4
            System.out.println(treeMap.ceilingKey(4));//>=4 离4最近的K
​
            // O(logN)
​
        }
    }

标签:head,队列,System,链表,int,println,数据结构,public,out
来源: https://www.cnblogs.com/wybqjcdd/p/16358244.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有