字符串缓冲区
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;
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++;
}
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];
for (int i = 0; i < a.length; i++)
buckets[ (a[i]/exp)%10 ]++;
for (int i = 1; i < 10; i++)
buckets[i] += buckets[i - 1];
for (int i = a.length - 1; i >= 0; i--) {
output[buckets[ (a[i]/exp)%10 ] - 1] = a[i];
buckets[ (a[i]/exp)%10 ]--;
}
for (int i = 0; i < a.length; i++)
a[i] = output[i];
}
public static void radixSort(int[] a) {
int exp;
int max = getMax(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):平方阶排序:O(N^2) :各类简单排序,如 直接插入、直接选择、冒泡排序;
(2):线性对数阶排序:O(N*Log2N):快速排序、堆排序、归并排序
(3):线性排序O(N):基数排序
空间复杂度:
(1)辅助存储O(1)排序:直接插入、直接选择、希尔排序、冒泡排序和堆排序;
(2)辅助存储O(nlog2n)排序:快速排序
(3)辅助存储O(n)排序:归并排序
(4)辅助存储O(n+rd)排序:基数排序
还有所谓的算法稳定性问题:交换前后相同的值的角标不变动,就说它是稳定的
稳定的排序算法:冒泡排序、插入排序、归并排序和基数排序
不是稳定的排序算法:选择排序、快速排序、希尔排序、堆排序