皮卡丘的皮Javase 0729--StringBuffer、六大排序(冒泡、选择、希尔、基数、快速、直插)及其空间时间复杂度

2 篇文章 0 订阅
1 篇文章 0 订阅

字符串缓冲区

StringBuffer 线程安全的可变字符序列,
StringBuffer 的构造方法:
	public StringBuffer():				      无参构造方法
	public StringBuffer(int capacity):	      指定容量的字符串缓冲区对象
 	public StringBuffer(String str):		  指定字符串内容的字符串缓冲区对象
	public int capacity():返回当前容量。	理论值
	public int length():返回长度(字符数)。 实际值
    public StringBuffer append(String str):	  
    可以把任意类型数据添加到字符串缓冲区里面,并返回字符串缓冲区本身
	public StringBuffer insert(int offset,String str):
    在指定位置把任意类型的数据插入到字符串缓冲区里面,并返回字符串缓冲区本身,还有
 delete  replace  substring与String类差别不大,两者的转换如下: 
   A:String -- StringBuffer
	a:通过构造方法
	b:通过append()方法
   B:StringBuffer -- String
	a: 使用substring方法
	b:通过构造方法
	c:通过toString()方法    
参数传递的问题:引用类型作为参数传递,形参会变,但 String 类型属于值传递,也就是说 new string后,调用完弹栈原有的string 还在举例:
public static void main(String[] args) {
        String str= "abc";
        change(str);
        System.out.println(str);
    }
    public  static  void  change(String str){
        str+="你好";
        System.out.println(str);
    }
}
输出结果为:abc你好
          abc
补充:Integer 同样有值得注意的地方  ==  与 equals 

数组排序方式

数组中的无序元素,通过交换移动的方式,使数组元素有序排列,话不多说,直接代码展示
冒泡排序:
  int[] arr = {24, 69, 80, 57, 13};
        //冒泡排序,数组中元素两两比较,大的元素后放,一轮之后,最大的元素出现在最后面
        for (int j = 0; j < arr.length-1; j++) {
            for (int i = 0; i < arr.length - 1-j; i++) {
                if (arr[i] > arr[i + 1]) {
                    int t = arr[i];
                    arr[i] = arr[i + 1];
                    arr[i + 1] = t;
                }
            }
        }
        System.out.println(Arrays.toString(arr));

选择排序:
        //选择排序,找数组最小的,把最小的放第一个然后剩余数组找最小放第二个
        int[] arr = {24, 69, 80, 57, 13};
        for (int i = 0; i < arr.length - 1; i++) {
            int min = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[j] <arr[min]) {        //相对于交换所有数组的值,优化一下,交换角标
                    min = j;
                }
            }
            if (min != i) {                   //一轮过后,若角标变化,交换一次即可
                int t = arr[i];
                arr[i] = arr[min];
                arr[min] = t;
            }
        }
        System.out.println(Arrays.toString(arr));
    
直接插入排序: 
        int[] arr = {24, 69, 80, 57, 13}for (int i = 1; i < arr.length; i++) {
            int temp=i;                   //中间变量的设置若取为i,  i++与i--冲突
            while(temp>0&&arr[temp]<arr[temp-1]){
                int t = arr[temp];
                arr[temp] = arr[temp-1];
                arr[temp-1] = t;
                temp--;                   //中间变量不止跟前一个比较,要跟所有前面的有序元素都比较
            }
        }
        System.out.println(Arrays.toString(arr));
简单插入排序的升级版:希尔排序
希尔排序:对于大规模的无序数组,插入排序就显得笨拙了些(相邻元素交换,形象一点的说就是一步步挪),不如将所有整个无序数组先分为若干个小规模的数组,小数组内部吸纳进行排序,再对小规模的数组再进行拆分,可以预见拆分到小数组里只有一个元素时,排序完成。
希尔排序的关键在于小数组的长度,有的地方叫增量,也可以叫步长。想当然我们将步长定为大数组长度的一半。代码如下:  
        public static void main(String[] args) {
        int[] arr = {20, 20, 6, 8, 9, 1, 23, 1, 4, 5};
        for (int gap = arr.length / 2; gap > 0; gap/=2) { //定义步长为长度一半,且二分
            for (int i = gap; i < arr.length; i++) {
                int j = i;
                int temp = arr[i];
                while (j -gap>= 0 && temp < arr[j-gap]) {  //若中间变量小于它(角标减步长)也就是对比量时,交换
                    arr[j] = arr[j - gap];
                    j -= gap;
                }
                arr[j] = temp;
            }
        }
        System.out.println(Arrays.toString(arr));
    }
快速排序:
public class quicksort {
    private  quicksort(){
    }
    public static void quicksort(int[] arr,int start,int end){
        if(start<end){
            int index=getindex(arr,start,end);
            quicksort(arr,start,index-1); //快排中学选择基准数,按比它大小分为左右两个区间,此为基准数的左区间,根据需求升序降序,放入比基准数大或小的数进去
            quicksort(arr,index+1,end);   //右区间
        }
    }
//快排的精髓:挖坑填数
    public static  int   getindex(int[] arr,int start,int end){
       int i=start;
       int j=end;
       int x=arr[i];   //定义基准数
       while(i<j) {
           // 由后向前找比他小的数,然后把他填进基数坑
           while (arr[j] >= x) {
               j--;     //  比他大,不要
           }
           if (i < j) { //比他小 填进去
               arr[i] = arr[j];
               i++;    //顺便i增加,不与自身进行比较
           }
           while (arr[i] < x) {//从前向后找大的
               i++;
           }
           if (i < j) {
               arr[j] = arr[i];
               j--;
           }
       }
       arr[j]=x;//,当所有坑挖完之后,这时只有基准值还没入坑,将基准数填进去
        return j;
    }
}
基数排序:基数排序的思路很简单,创建一个空间很大的数组,将数组角标对应原来数组值,再遍历输出,即为排序后的结果,同样缺点也是空间开销大,所以优化下。基数排序是对==关键字==
(高低分位比较)的排序,排序方法仍要使用一种稳定的排序方法。举例:
public class radixsort {
    private static int getMax(int[] a) {
        int max;
        max = a[0];
        for (int i = 1; i < a.length; i++)
            if (a[i] > max)
                max = a[i];
        return max;
    }   //遍历数组求最大值,得到最大位数,确定循环次数
    private static void countSort(int[] a, int exp) {
        int[] output = new int[a.length];    // 存储"被排序数据"的临时数组
        int[] buckets = new int[10];         //10个桶
        // 将数据出现的次数存储在buckets[]中
        for (int i = 0; i < a.length; i++)
            buckets[ (a[i]/exp)%10 ]++;

        // 更改buckets[i]。更改后的buckets[i]的值,指向在output[]中的位置。
        for (int i = 1; i < 10; i++)
            buckets[i] += buckets[i - 1];

        // 将数据存储到临时数组output[]中
        for (int i = a.length - 1; i >= 0; i--) {
            output[buckets[ (a[i]/exp)%10 ] - 1] = a[i];        //级数对应的数的那个桶指向的角标
            buckets[ (a[i]/exp)%10 ]--;
        }

        // 将排序好的数据赋值给a[]
        for (int i = 0; i < a.length; i++)
            a[i] = output[i];

    }

    public static void radixSort(int[] a) {
        int exp;    // 级数
        int max = getMax(a);    // 数组a中的最大值
        // 从个位开始,对数组a按个十百进行排序
        for (exp = 1; max/exp > 0; exp *= 10)
            countSort(a, exp);
    }

    public static void main(String[] args) {
        int i;
        int a[] = {53, 3, 542, 748, 14, 214,};

        radixSort(a);    // 基数排序
        for (i=0; i<a.length; i++)
            System.out.printf("%d ", a[i]);
        System.out.printf("["+"\n"+"]");
    }
}
二分查找的前提是有序的数组元素,如果无序数组则二分查找意义不大。
二分查找:
        int[] arr = {10, 20, 30, 40, 70, 90, 100};
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入搜索值");
        int x = sc.nextInt();
        int index=getindex(arr,x);
        System.out.println(index);
    }
    private static int getindex(int[] arr,int ele) {
        int minindex = 0;                 //定位数组左端
        int maxiindex = arr.length - 1;   //定位数组右端
        int midindex = (minindex + maxiindex) / 2;  //二分法定位中间角标
        while (minindex <= maxiindex) {
            if (ele == arr[midindex]) {          
                return midindex;
            } else if (ele < arr[midindex]) {     
                maxiindex = midindex - 1;          //区间左移
            } else if (ele > midindex) {
                minindex = midindex + 1;           //区间右移
            }
            midindex = (minindex + maxiindex) / 2;  //二分
        }
        return -1;       //找不到,报错-1;
    }

总结

各排序算法的时间复杂度:
(1):平方阶排序:O(N^2) :各类简单排序,如 直接插入、直接选择、冒泡排序;
(2):线性对数阶排序:O(N*Log2N):快速排序、堆排序、归并排序
(3):线性排序O(N):基数排序
空间复杂度:
(1)辅助存储O(1)排序:直接插入、直接选择、希尔排序、冒泡排序和堆排序;
(2)辅助存储O(nlog2n)排序:快速排序
(3)辅助存储O(n)排序:归并排序
(4)辅助存储O(n+rd)排序:基数排序
还有所谓的算法稳定性问题:交换前后相同的值的角标不变动,就说它是稳定的
稳定的排序算法:冒泡排序、插入排序、归并排序和基数排序
不是稳定的排序算法:选择排序、快速排序、希尔排序、堆排序
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值