栈,队列与位运算的总结

文章目录栈与队列的区别实现栈的方式如何用O(1)的时间复杂度求栈中最小元素如何实现队列如何用两个栈模拟队列操作判断一个数是否为2的n次方如何求二进制数中1的个数栈与队列的区别栈和队列是两种重要的线性数据结构.栈是后进先出,队列是先进先出.实现栈的方式方法1:使用java.util包下的Stack方法2:使用数组实现public class 数组实现栈<E> { priv...
摘要由CSDN通过智能技术生成

栈与队列的区别

栈和队列是两种重要的线性数据结构.
栈是后进先出,队列是先进先出.

实现栈的方式

方法1:使用java.util包下的Stack
方法2:使用数组实现

public class 数组实现栈<E> {
	private Object[] stack;
	private int size;
	public 数组实现栈() {
		stack=new Object[10];//初始长度
	}
	//判断栈是否为空
	public boolean isEmpty() {
		return size==0;
	}
	public E peek() {
		if (isEmpty()) {
			return null;
		}
		return (E) stack[size-1];
	}
	public E pop() {
		E e=peek();
		stack[size-1]=null;
		size--;
		return e;
	}
	private void ensureCapacity(int size) {
		int len=stack.length;
		if (size>len) {
			int newlen=10;
			stack=Arrays.copyOf(stack, newlen);
		}
	}
	public E push(E item) {
		ensureCapacity(size+1);
		stack[size++]=item;
		return item;
	}
	
public static void main(String[] args) {
	数组实现栈<Integer> s=new 数组实现栈<>();
	s.push(1);
	s.push(2);
	System.out.println("栈中元素个数:"+s.size);
	System.out.println("栈顶元素为:"+s.pop());
	System.out.println("栈顶元素为:"+s.pop());
}
}

方法3:使用链表实现

class Node<E>{
	Node<E> next=null;
	E data;
	public Node(E data) {
		// TODO Auto-generated constructor stub
		this.data=data;
	}
}
public class 链表实现栈<E> {

	Node<E> top =null;
	//头插法
	public void push(E data) {
		Node<E> newNode=new Node(data);
		newNode.next=top;
		top=newNode;
	}
	public boolean isEmpty() {
		return top==null;
	}
	public E pop() {
		if (this.isEmpty()) {
			return null;
		}
		E data=top.data;
		top=top.next;
		return data;
	}
	public E peek() {
		if (isEmpty()) {
			return null;
		}
		return top.data;
	}
}

如何用O(1)的时间复杂度求栈中最小元素

如果当前入栈的元素比原来栈中的最小值还小,则把这个值压入保存最小元素的栈中.在出栈时,如果当前出栈的元素恰好为当前栈中的最小值,保存最小值的栈顶元素也出栈,使得当前最小值变为其入栈之前的那个最小值.
在这里插入图片描述
在这里插入图片描述

如何实现队列

方法1:使用数组
在这里插入图片描述
在这里插入图片描述
方法2:使用链表
在这里插入图片描述
在这里插入图片描述

如何用两个栈模拟队列操作

使用栈A和栈B模拟队列Q
命令栈A为插入栈 ,栈B为弹出栈
入队列的操作为 入栈A
出队列的操作为 :
情形1: 若栈B不为空,直接弹出栈B的数据
情形2:若栈B为空,依次弹出栈A的数据放入栈B中,再弹出栈B的数据.

实现代码如下:

public class 两个栈模拟队列<E> {

	private Stack<E> s1=new Stack<>();
	private Stack<E> s2=new Stack<>();
	public synchronized void put(E e) {
		s1.push(e);
	}
	public synchronized E pop() {
		if (s2.isEmpty()) {
			while(!s1.isEmpty()) {
				s2.push(s1.pop());
			}
		}
		return s2.pop();
	}
	public synchronized boolean empty() {
		return s1.isEmpty()&&s2.isEmpty();
	}
	public static void main(String[] args) {
		两个栈模拟队列<Integer> q=new 两个栈模拟队列<Integer>();
		q.put(1);
		q.put(2);
		System.out.println("队列首元素:"+q.pop());
		System.out.println("队列首元素"+q.pop());
	}
}

判断一个数是否为2的n次方

最直观的解法是用1做移位操作,然后判断移位后的值是否与给定的数相等.这个算法的时间复杂度O(lgn).

代码实现如下:

public static boolean isPower(int n) {
	if (n<1) {
		return false;
	}
	int i=1;
	while(i<=n) {
		if (i==n) {
			return true;
		}
		i<<=1;
	}
	return false;
}

算法优化:
观察发现,2的n次方转为2进制后只有1位是1如num=00010000,那么num-1=00001111,将00010000和00001111进行与(&)操作结果为0.
推出:若num为2的n次方,则num&(num-1)==0.

代码实现如下:

public static boolean isPower2(int n) {
	if (n<1) {
		return false;
	}
	int m=n&(n-1);
	return m==0;
}

如何求二进制数中1的个数

我们可以通过位操作完成算法.
首先判断这个数的最后一位是否为1,如果为1,计数器加1,然后通过右移丢弃最后一位.
循环执行直到这个数等于0为止.

代码实现:

public static int countOne(int n) {
	int count=0;
	while(n>0) {
		//如果最后一位是1
		if ((n&1)==1) {
			count++;
		}
		n>>=1;
	}
	return count;
}

算法优化:
我们在判断一个数是否为2的n次方时说到了一个特性:2进制数0100&(0100-1)=0,即如果2进制数n有1,则n&(n-1)后这个1必为0.

代码实现:

public static int countOne2(int n) {
	int count=0;
	while(n>0) {
		n=n&(n-1);
		count++;
	}
	return count;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值