一.二进制,位运算,移位运算
1.二进制
对于原码, 反码, 补码而言, 需要注意以下几点:
(1).Java中没有无符号数, 换言之, Java中的数都是有符号的;
(2).二进制的最高位是符号位, 0表示正数, 1表示负数;
(3).正数的原码, 反码, 补码都一样;
(4).负数的反码=它的原码符号位不变, 其他位取反;
(5).负数的补码=它的反码+1;
(6).0的反码, 补码都是0;
(7).在计算机运算的时候, 都是以补码的方式来运算的.
2.位运算
Java中有4个位运算, 分别是按位与&, 按位或|, 按位异或^, 按位取反~, 它们的运算规则为:
3.移位运算
Java中有3个移位运算符, 分别是算术右移>>, 算术左移<<, 逻辑右移>>>, 它们的运算规则为:
4.简单的程序实例
public class Demo1 {
public static void main(String[] args) {
System.out.println(~2);
System.out.println(2&3);
System.out.println(2|3);
System.out.println(~-5);
System.out.println(13&7);
System.out.println(5|4);
System.out.println(-3^3);
}
}
运行结果:
-3
2
3
4
5
5
-2
public class Demo2 {
public static void main(String[] args) {
System.out.println(1>>2);
System.out.println(-1>>2);
System.out.println(1<<2);
System.out.println(-1<<2);
System.out.println(3>>>2);
}
}
运行结果:
0
-1
4
-4
0
二.约瑟夫问题
约瑟夫问题: 设编号为1,2,3...n的n个人围坐一圈, 约定编号为k(1<=k<=n)的人从1开始报数, 数到m的那个人出列, 它的下一位又从1开始报数, 数到m的那个人又出列, 依次类推, 直到所有人出列为止, 由此产生一个出队编号的序列.
public class Demo3 {
public static void main(String[] args) {
CycleLinkList cycleLinkList=new CycleLinkList();
cycleLinkList.setCycleLinkListLength(10);
cycleLinkList.initCycleLinkList();
cycleLinkList.Josephu(4, 6);
}
}
/**
* 节点结构
*/
class Node {
//编号
private int number;
//指向下一个节点的引用
private Node nextNode=null;
//构造函数
public Node(int number) {
this.number=number;
}
//设置nextNode节点
public void setNextNode(Node nextNode) {
this.nextNode = nextNode;
}
//得到nextNode节点
public Node getNextNode() {
return nextNode;
}
//得到编号
public int getNumber() {
return number;
}
}
/**
* 循环链表
*/
class CycleLinkList {
//链表的长度
private int length=0;
//指向链表头结点的引用
private Node firstNode=null;
/**
* 设置链表的长度
* @param len 链表长度
*/
public void setCycleLinkListLength(int len) {
this.length=len;
}
/**
* 初始化循环链表
*/
public void initCycleLinkList() {
//定义一个临时节点
Node tempNode=null;
for(int i=1;i<=length;i++) {
//头节点
if(1==i) {
Node headNode=new Node(i);
this.firstNode=headNode;
tempNode=headNode;
}else {
//尾节点
if(length==i) {
Node node=new Node(i);
tempNode.setNextNode(node);
tempNode=node;
//将尾节点的nextNode引用指向链表的头节点firstNode
tempNode.setNextNode(firstNode);
}else { //其它节点
Node node=new Node(i);
tempNode.setNextNode(node);
tempNode=node;
}
}
}
}
/**
* 打印循环链表
*/
public void printCycleLinkList() {
Node tempNode=this.firstNode;
do {
System.out.println(tempNode.getNumber());
tempNode=tempNode.getNextNode();
} while (tempNode!=this.firstNode);
}
/**
* 约瑟夫问题
* @param k 从第k个人开始报数
* @param m 数m下
*/
public void Josephu(int k, int m) {
//判断k的合法性
if( !(k>=1 && k<=this.length) ) {
System.out.println("传入的k不正确");
System.exit(-1);
}
//定义一个临时节点
Node tempNode=this.firstNode;
//先找到第k个人
for(int i=1;i<k;i++) {
tempNode=tempNode.getNextNode();
}
//数m下,将数到m的节点从循环链表中删除
//有两种情况需要考虑,
//第一种:m=1的情形
//第二种:除了第一种的特殊情况,其他的只要找到数到m节点的的前一个节点即可,即数m-1下
//第一种情形
if(1==m) {
//从当前节点依次输出出队序列
int len=this.length;
while( (len--)>0) {
System.out.println(tempNode.getNumber());
tempNode=tempNode.getNextNode();
}
}
//第二种情形
else {
//记录出队的节点数
int cnt=0;
do {
//数(m-1)下
for(int j=1;j<(m-1);j++) {
tempNode=tempNode.getNextNode();
}
//出队的节点
System.out.println(tempNode.getNextNode().getNumber());
//记录出队的节点数
cnt++;
//删除数到m的节点
Node tempNode2=tempNode.getNextNode().getNextNode();
tempNode.setNextNode(tempNode2);
//更新tempNode,从数到m的人下一个开始报数
tempNode=tempNode2;
} while (cnt!=this.length);
}
}
}
运行结果:
9
5
2
10
8
1
4
3
7
6