java之一些代码

排序

排序后即可找出最大、最小、中位数、第N大/小的数

1、交换元素排序:冒泡排序,快速排序(综合效率高)

冒泡的算法思想:相邻元素比较,看是否满足大小关系,不满足则交换;

一次冒泡,至少一个元素移动到首/尾;n个元素,重复n次;

算法优化:某次冒泡过程,没有数据交换,则完全排序,不用执行后续冒泡操作;

第一趟:a[0]与a[1]比较,逆序则交换;然后a[1]和a[2]比较,逆序则交换...最后最大的被冒泡到最后;

public void bubbleSort(int[] arr){
    int n=arr.length;
    if(n<=1)
        return;
    for(int i=0;iarr[j+1]){
                int tmp=arr[j];
                arr[j]=arr[j+1];
                arr[j+1]=tmp;
                flag=true;//表示有数据交换
            }
        }
        if(!flag)
            break;//没有数据交换
    }
}

原地排序:只涉及相邻数据交换,只需要常量级临时空间,即空间复杂度为o(1);稳定排序:只有交换才能改变元素的前后顺序。当相邻元素相等时,不做交换;时间复杂度:最好为数据已经有序,则进行一次排序即o(n);最坏为逆序,做n次排序即o(n*n);平均为o(n*n);循环次数表示时间复杂度,i循环n-1次(即n-1次比较),最坏情况下j循环n次;

   

快速排序:i,j表示从左到右的序号,选区基准数base(如i0);

    一趟:从右向左找比base小的数,交换;然后从左开始找比base大的数,交换;再从右开始找...直到base左边全部比base小,右边全部比base大,然后第二趟...

    如(46,79,56,38,40,84)第一趟以后变为(40,38,46,56,79,84);

    缺点:源数据越有序越慢(左右两边递归);   

void QuickSort(int &a, int left,int right) {  //left和right表示数组最左边和最右边的值
    int i, j,temp;
    int lIndex= left;
    int rIndex= right;
    int index = a[(left + right) / 2];
    while (lIndex < rIndex) {
        while (a[lIndex < index]) {
             ++lIndex;
        }
        while (a[rIndex>index]) {
            --rIndex;
        }
        if (lIndex <= rIndex) {
            temp = a[lIndex];
            a[lIndex] = a[rIndex];
            a[rIndex] = temp;
            --rIndex;
            ++lIndex;
        }
    }
    If (lIndex == rIndex) {
        lIndex++;
    }
    if (left < rIndex) {
        QuickSort(a, left, lIndex - 1);
    }
    if (lIndex < right) {
        QuickSort(a, rIndex + 1, right);
    }
}

2、插入数据排序

思想:元素分为未排序和已排序区间,从未排序区间取出元素按关键码插入已排序区间的合适位置,直到未排序区间没有元素;

        主要方法:(直接)插入排序(增量为1),希尔排序(增量为d的子序列排序后,再排序);

第一趟:a[0]不用排序,从a[1]开始,设置它为value;j为它前面的有序去遍历,且从后向前即j--,当a[j]>value时,则将它后移一位(然后再比较a[j-1]与value)直到有一个数a[j]<=value了,则此数的后一个位置插入value;

原地排序:空间复杂度o(1);稳定排序:相同元素,后出现的插入到先出现的后边;时间复杂度:最好即已有序,o(1);最坏为逆序,o(n*n);平均为o(n*n)(插入一次为o(n),循环n次);应用广泛的为插入排序(冒泡排序有3个赋值操作即交换,而插入排序只有一个数据移动);

public void insertSort(int[] arr){
    if(n<=1)
        return;
    int length = arr.length;
    for(int i=1;i=0;--j){//查找插入的位置
           if(arr[j]>value)
               arr[j+1]=arr[j];//数据移动
           else
               break;//无序区第一个元素比有序区最后一个元素还大,则无需再比较
        }
        if(arr[j+1] != value)
            arr[j+1]=value;//插入数据
    }
}

3、选择元素排序:比较->选出>交换;简单选择排序,堆排序

第一趟:k=i=0,j从i+1=1开始到最后,遍历每个元素并与a[0]比较;当a[j]较小时,记录k变为j,继续遍历j,直到k是最小元素的下标j,退出j循环(即选出);比较k和i,k变了,则交换a[i]和a[k],则此时a[i]为最小;然后i++,执行第二趟遍历;不稳定;效率高(针对下标操作)

void SelectionSort(int[] arr) {
    int i, j, minIndex;
    int lenth=arr.length;
    int index;
    for (i = 0; i < lenth-1; i++) {
        minIndex = i;
        for (j = i + 1; j < lenth;j++) {
           if (arr[j] < arr[minIndex])
           minIndex = j;
        }
        if (minIndex != i) {
           index = arr[i];
           arr[i] = arr[minIndex];
           arr[minIndex] = index;
        }
    }
}

4、实现二叉排序树

java之一些代码_第1张图片

 

//二叉排序树
public class TestBinaryTree {
    public static void main(String[] args) {
        TestBinaryTree node=new TestBinaryTree();
        node.addData(4);
        node.addData(7);
        node.addData(98);
        node.addData(46);
        node.addData(4);
        node.addData(2);
        node.addData(45);
        node.addData(84);
        node.print();
    }

    private Node node;
    //数据进来,如果是第一个数,则作为根节点,否则调用节点添加函数
    public void addData(int data){
        if (null==node){
            node=new Node(data);
        }else {
            node.addNode(data);
        }
    }
    //从根节点按照中序遍历打印二叉树
    public void print(){
        this.node.printNodeData();
    }
}

class Node{
    private int data;
    private Node leftNode;
    private Node rightNode;

    public Node(int data) {
        this.data = data;
    }

    /*
    添加节点:判断进来的数据:
    1、当前数据小,应放在节点左边
        如果做节点不存在,则以当前数据新建做节点;
        否则递归做节点,即继续比较做节点的数据与当前数据,判断当前数据应在左节点的哪边;
    2、右边同理
    */
    public void addNode(int data){
        if (this.data>data){
            if (null==this.leftNode){
                this.leftNode=new Node(data);
            }else {
                this.leftNode.addNode(data);
            }
        }else {
            if (null==this.rightNode){
                this.rightNode=new Node(data);
            }else {
                this.rightNode.addNode(data);
            }
        }
    }

    //中序遍历:左-中-右
    public void printNodeData(){
        if (null!=this.leftNode){
            this.leftNode.printNodeData();
        }
        System.out.print(this.data+" -> ");
        if (null!=this.rightNode){
            this.rightNode.printNodeData();
        }
    }
}

二、获取指定范围内不重复随机数

方法1:循环产生随机数value -> value与数组元素遍历比较 –>不同则添加进数组

       //产生不重复的随机数或者随机字符   

 public static void getRandomNumberOrChar() {
       //产生n个随机数,随机数作下标返回n个字符
    String string="abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    char[] cs=new char[10];
    for (int i = 0; i < cs.length; i++) {
        int random=(int) (Math.random()*string.length());
        System.out.print(random+"\t");
            //可以先产生不重复的随机数保存到数组(重复了就不保存),再用数组下标来指定字符;
            //以下是产生了字符,再不添加重复的元素(但是被填充了空格???)
        boolean flag=false;
        for(int j=0;j

方法2:产生随机数 -> 存入Set集合

       HashSet set; set.add(value);

方法3:将范围内值作为个数组,产生一个随机值后,将此值与数组最后一个元素交换;然后在除去最后一个元素的数组中产生第二个随机值;如此重复

public static void random(int[] range, int[] numbers) {
        Random random = new Random();
        int rangeIndex = -1;
        for (int i = 0; i < numbers.length; i++) {
            rangeIndex = random.nextInt(range.length - i);//产生范围内一个随机数作为下标
            numbers[i] = range[rangeIndex ];//范围内下标处的数作为随机数数组

            int temp = range[rangeIndex ];
            range[rangeIndex ] = range[range.length - 1 - i];
            range[range.length - 1 - i] = temp;
        }
    }

 

三、判断是否是回文字符串

   

boolean isHuiWen(String text) {
       int length = text.length();
       for (int i = 0; i < length / 2; i++) {
           if (text.toCharArray()[i] != text.toCharArray()[length - i - 1]) {
               return false;
           }
       }
       return true;
}

 

四、JAVA回调机制

    类A的a()方法调用类B的b()方法,b()方法会调用类A的某些方法,即双向调用;

    计算器实例:

       //同步回调,回调接口

       interface CallBackInterface{

           public void getResult(int a,int b,int result);

       }

       //A类:实现接口

       class A implements CallBackInterface{

           属性a,b和构造器以及调用B类的方法,以自身对象做参数

           public void addA(){

              new B().add(a,b,this);

           }

           @override

           public void getResult(int a,int b,int result){

              System.out.println(a+"+"+b+"="+result)

           }

       }

       //B类:以(实现了接口的A类做参数,然后调用A类方法)

       class B{

           public void addB(int a,int b,CallBackInterface callbackInterface){

              int result=a+b;

              callBackInterface.getResult(a,b,result);

           }

       }

       主函数:实例化A并调用addA();

    异步回调:被调用方的方法在收到某种讯息或发生某种事件时(异步消息通知),才去调用对方的方法

    或者说不必等被调用方法一定执行完而仍会继续执行

    在addB()中的调用A类的方法之前:

       try { Thread.sleep(5 * 1000); }

       catch (InterruptedException e) { e.printStackTrace(); }

    而addA方法需要实现多线程,即

       new Thread(new Runnable(){

           public void run(){

              new B().add(a,b,this);

           }

       }).start();

      

五、统计次数

    1.统计数组中所有元素出现的次数/统计字符串中所有字符出现的次数(将参数换为String且转为char[],map类型为

public static void countAll(String[] stringArr) {
    Map map=new HashMap();
    for(String string:stringArr){
        Integer integer=map.get(string);
        if (integer==null) {
            map.put(string, 1);
        } else {         
            map.put(string, integer+1);
        }
           //找出所有包含某个字符(或子串)的字符串
        for(int i=0;i

 

2.统计文件中某个字符串出现的次数

   

public static int statisticalNumber(String fileName,String str) throws Exception {
       int count = 0;
       BufferedReader bf = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));   //构造文件输出流
       String readLine ;
       StringBuilder sb = new StringBuilder();
       while((readLine = bf.readLine() )!= null) {
           sb.append(readLine); //将数数据写入添加到缓冲字符串
       }

       //方式1
       int a = 0;
       while((a = sb.indexOf(str)) != -1) {
          sb = sb.delete(a, a + str.length()); //查找字符串在缓冲字符串中的位置,查到则表示存在;删除,统计删除次数
              count++;
       }

       //方式2:将sb再转为长String,并用str做切割符,切成字符串数组后数组长度-1即表示切割了几次,即string出现次数
       count=sb.toString().split(str).length-1;
       //使用正则表达式相关API
       Pattern p=Pattern.compile(str);
       Matcher m=p.mathcer(sb);//放在长串中匹配
       while(m.find()) num++;

       return count;
}
    //filePath=”F:/test.txt”等价“F:\\test.txt”,第一个\是转义字符

六、兔产子问题-裴波那切函数1,1,2,3,5,8,13,21…

    规律:后一项=前两项之和

//递归:
void fibinacci(int n){
        if(n==1||n==2) return 1;
        else return fibinacci(n-1)+fibinacci(n-2);
}

//非递归之for循环/数组:
long fibinacci(long n){
       long a=1;int b=1; //long[] arr=new long[n];arr[1]=arr[2]=1;
       for(int i=3;i<=n;i++){
            b=a+b;//arr[i]=arr[i-1]+arr[i-2];
            a=b-a;
        }
       return b;//return arr[n-1];
}

七:约分-最大公约数-最小公倍数
   

 //numrator分子,denominator分母;辗转相除法
    public static void reduceToLowest(int numrator,int denominator) {
       if (numrator<0||denominator<=0) {
           System.out.println("非法分数");
           return;
       }
       System.out.println("原始分数为:"+numrator+"/"+denominator);
       if(numrator==denominator){
           System.out.println(1);
       } else {
           int small=numrator

八:全排列

//第一趟:选定(第)一个字符,若干次(与它后面的)交换(当它被交换到末尾时为出口),得出基于它的全排列;然后将它复位;LinkList保存每一种排列

    //第二趟:选定下一个字符

    //去重排列:选定的字符与它不同的字符交换

    public static void allPermutation(String str){

        if(str == null || str.length() == 0)

            return;

        //保存所有的全排列

        LinkedList listStr = new LinkedList();

        permutation(str.toCharArray(), listStr, 0);

        print(listStr);//打印全排列

    }

 

    private static void permutation(char[] c, LinkedList list, int start){

        if(start == c.length-1)

            list.add(String.valueOf(c));

        else{

            for(int i = start; i <= c.length-1; i++){

                swap(c, i, start);//相当于: 固定第 i 个字符

                permutation(c, list, start+1);//求出这种情形下的所有排列

                swap(c, start, i);//复位

            }

        }

    }

   

    private static void swap(char[] c, int i, int j){

        char tmp;

        tmp = c[i];

        c[i] = c[j];

        c[j] = tmp;

    }

   

    private static void print(LinkedList list){

        Collections.sort(list);//使字符串按照'字典顺序'输出

        for (String str : list) {

            System.out.println(str);

        }

        System.out.println("size:" + list.size());

}

 

九、打印空心菱形

   

public static void print(int row){
       if (row%2==0) {
           row++;//行数为奇数
       }
       //上本部分
       for (int i = 0; i < row/2+1; i++) {
           //左上角空白
           for (int j = row/2+1; j >i+1; j--) {
              System.out.print(" ");
           }
           for (int j = 0; j < 2*i+1; j++) {
              if (j==0||j==2*i) {               
                  System.out.print("*");//菱形边缘
              }else {
                  System.out.print(" ");//菱形中间空白
              }
           }
           System.out.println("");
       }
       //下半部分
       for (int i = row/2+1; i < row; i++) {
           //左下角空白
           for (int j = 0; j 

 

十、长数字的分组格式输出,如金额每隔3个数一个符号隔开

   

//digit为分位位数如3位为一组,每隔三个数插入一个逗号
public static String formatNumber(int digit,long value) {
       StringBuffer sb=new StringBuffer(String.valueOf(value));
       sb=sb.reverse();
       int length=sb.length();
       if (digit==0||digit>length) {
           digit=length;
       }

       int count=0;//分位后组数
       if(length%digit==0)
           count=length/digit-1;
       else {
           count=length/digit;
       }

       for (int i = 0; i < count; i++) {
           sb=sb.insert((i+1)*digit+i,",");//注意,添加的位置计算
       }

       System.out.println(sb.reverse().toString());
       //return sb.reverse().toString();
       return null;
}

 

你可能感兴趣的:(java之一些代码)