栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

常见的数据结构

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

常见的数据结构

单链表和双链表 

//单向链表节点结构
public class Node {
    //内容 整型
    public int value;
    //next指针 Node型
    public Node next;
    //给内容赋值
    public Node(int data) {
        value = data;
    }
}
//双向链表节点结构
public class DoubleNode {
    //内容整型
    public int value;
    //last指针 DoubleNode型
    public DoubleNode last;
    //next指针 DoubleNode型
    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 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 DoubleEndsQueue {
		public Node head;
		public Node tail;

		//新节点成为头
		public void addFromHead(T value) {
			Node cur = new Node(value);
			if (head == null) {
				head = cur;
				tail = cur;
			} else {
				cur.next = head;
				head.last = cur;
				head = cur;
			}
		}

		//新节点成为尾
		public void addFromBottom(T value) {
			Node cur = new Node(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 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 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 {
		private DoubleEndsQueue queue;

		public MyStack() {
			queue = new DoubleEndsQueue();
		}

		//在头部添加数据  头部属于后进
		public void push(T value) {
			queue.addFromHead(value);
		}

		//从头部去除数据  头部属于先出
		public T pop() {
			return queue.popFromHead();
		}

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

	}

双向链表实现队列 

    //先进先出
	public static class MyQueue {
		private DoubleEndsQueue queue;

		public MyQueue() {
			queue = new DoubleEndsQueue();
		}

		//在头部添加数据  头部属于后进
		public void push(T value) {
			queue.addFromHead(value);
		}
		//在后面去除数据  尾部属于先出
		public T poll() {
			return queue.popFromBottom();
		}

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

     }

怎么用数组实现不超过固定大小的队列和栈?

栈:正常使用

队列:环形数组 

public static class MyQueue {
		private int[] arr;
        //最后加入数据下标 加数据的位置
		private int pushi;// end
		//最先加入数据下标 减数据的位置
        private int polli;// begin
		private int size;
		private final int limit;
        
        //起到记录的作用 limit是arr数组长度
		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++;
            //pushi的位置加入数据
			arr[pushi] = value;
            //没到底部加1,到底部返回0
			pushi = nextIndex(pushi);
		}

		public int pop() {
			if (size == 0) {
				throw new RuntimeException("队列空了,不能再拿了");
			}
			size--;
            //从polli的位置减数据
			int ans = arr[polli];
            //没到底部加1,到底部返回0
			polli = nextIndex(polli);
			return ans;
		}

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

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

	}

}

实现一个特殊的栈,在基本功能的基础上,再实现返回栈中最小元素的功能

(1)pop、push、getMin操作的时间复杂度都是 O(1)。

(2)设计的栈类型可以使用现成的栈结构。 

思路:方法一:设计两个栈,一个是数据栈,一个是最小栈。数据栈正常放数据,最小栈判断加入的数据是否小于上次压入的数据,如果小于,压入这次数据,如果大于,不压入数据,弹出时,数据栈直接弹,判断弹出的数据栈的值和最小栈的最小值是否相等,如果相等弹出最小栈最小值,否则不弹出。

方法二:设计两个栈,一个是数据栈,一个是最小栈。数据栈正常放数据,最小栈判断加入的数据是否小于上次压入的数据,如果小于,压入这次数据,如果大于,压入上次压入的数据。同步加,同步弹。

    //方法一:
    public static class MyStack1 {
		private Stack stackData;
		private Stack stackMin;

		public MyStack1() {
			this.stackData = new Stack();
			this.stackMin = new Stack();
		}
        
        //压入新数据
		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 stackData;
		private Stack stackMin;

		public MyStack2() {
			this.stackData = new Stack();
			this.stackMin = new Stack();
		}

		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);
		}

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

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

(1)如何用栈结构实现队列结构

    创建两个栈:push和pop栈

    push栈倒入pop栈,要一次性倒完

    看pop栈空不空,空了push栈才能倒

    public static class TwoStacksQueue {
		public Stack stackPush;
		public Stack stackPop;
        
        //创建两个栈
		public TwoStacksQueue() {
			stackPush = new Stack();
			stackPop = new Stack();
		}

		// push栈向pop栈倒入数据
		private void pushToPop() {
            //判断pop栈是否为空
			if (stackPop.empty()) {
                //判断push栈是否非空
				while (!stackPush.empty()) {
                    //将push栈的数据全部转移到pop栈中
					stackPop.push(stackPush.pop());
				}
			}
		}
        //加数据时往push栈中加,然后判断能不能往pop栈中倒
		public void add(int pushInt) {
			stackPush.push(pushInt);
			pushToPop();
		}
        //弹数据时,判断能不能往pop栈中倒,然后在pop栈中弹,
		public int poll() {
            //push和pop栈同时为空
			if (stackPop.empty() && stackPush.empty()) {
				throw new RuntimeException("Queue is empty!");
			}
			pushToPop();
			return stackPop.pop();
		}

		public int peek() {
            //push和pop栈同时为空
			if (stackPop.empty() && stackPush.empty()) {
				throw new RuntimeException("Queue is empty!");
			}
			pushToPop();
			return stackPop.peek();
		}
	}

(2)如何用队列结构实现栈结构  

思路:队列654321    栈后入先出弹出6 

           队列1:6         队列2:54321 

           队列1弹出6 

Queue tmp = queue;

queue = help;

help = tmp;

相当于使两个队列相互换名字,数据永远从queue中弹出

    public static class TwoQueueStack {
        
        //两个队列
		public Queue queue;
		public Queue help;

		public TwoQueueStack() {
			queue = new LinkedList<>();
			help = new LinkedList<>();
		}
        
        //插入数据
		public void push(T value) {
			queue.offer(value);
		}
        
        //弹出数据
		public T poll() {
            //判断queue的长度是否大于1
			while (queue.size() > 1) {
                //将queue中的数据弹出,放到help中,直到queue中的数据只有1个
				help.offer(queue.poll());
			}
            //ans记录queue弹出的数
			T ans = queue.poll();
            //tmp指向queue
			Queue tmp = queue;
            //queue指向help
			queue = help;
            //help指向tmp
			help = tmp;
            //返回queue弹出的数据
			return ans;
		}

		public T peek() {
			while (queue.size() > 1) {
				help.offer(queue.poll());
			}
			T ans = queue.poll();
			help.offer(ans);
			Queue tmp = queue;
			queue = help;
			help = tmp;
			return ans;
		}

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

	}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/885703.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号