Java学习第五篇:二进制(原码 反码 补码),位运算,移位运算,约瑟夫问题

一.二进制,位运算,移位运算

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

posted @ 2013-12-04 17:41  顺冉  阅读(1048)  评论(0编辑  收藏  举报