2.1接口、向量操作(追加、删除、倒置、插入)
java中String是不可变字符串,有一个类是StringBuffer,是“可变”字符串。这里自己写了一个类似于StringBuffer类的代码。
接口:
package Chap2;
public interface IStringBuffer {
public void append(String str);//追加字符串
public void append(char c);//追加字符
public void insert(int pos,char b);//指定位置插入字符
public void insert(int pos,String str);//指定位置插入字符串
public void delete(int start);//指定位置开始删除剩下的
public void delete(int start,int end);//指定位置开始删除结束位置-1
public void reverse();//反转
public int length();//返回长度
}
可变字符串操作:(做性能测试的时候尽量不要在for循环的判断部分使用计算,尤其是String.length()部分是耗时的!!)
package Chap2;
public class MyStringBuffer implements IStringBuffer{
int capacity = 16;
int length = 0;
char[] value;
public MyStringBuffer() {
value = new char[capacity];
}
public MyStringBuffer(String str) {
this();
if(null == str)
return;
if (capacity<str.length()) {
capacity = str.length() *2;//时间复杂度O(n),空间利用率<50%
value = new char[capacity];
}
if(capacity>=str.length()) {
char[] str_to_char = str.toCharArray();
for(int i = 0;i<str_to_char.length;i++) {
value[i] = str_to_char[i];
}
}
length = str.length();
}
@Override
public void append(String str) {
// TODO Auto-generated method stub
if(str.length()+length>capacity) {
capacity = (str.length()+length)*2;
char[] newvalue= value;
value = new char[capacity];
for(int i =0;i<length;i++) {
value[i] = newvalue[i];
}
}
int j = 0;
char[] tc = str.toCharArray();
int slen = str.length()+length;//耗时的部分,不要放进for的判断部分
for(int i = length;i<slen;i++) {
value[i] = tc[j++];
}
length = length+str.length();
}
@Override
public void append(char c) {
// TODO Auto-generated method stub
append(String.valueOf(c));
}
@Override
public void insert(int pos, char b) {
// TODO Auto-generated method stub
insert(pos,String.valueOf(b));
}
@Override
public void insert(int pos, String str) {
// TODO Auto-generated method stub
if(pos<0) {
System.out.println("插入失败");
return;
}
if(pos>=length) {
System.out.println("插入失败");
return;
}
if(null == str)
return;
//扩容
if((str.length()+length)>capacity) {
capacity = (str.length()+length)*2;
char[] newvalue = value;
value = new char[capacity];
for(int i = 0;i<length;i++) {
value[i] = newvalue[i];
}
}
length = str.length()+length;
System.out.println(length);
for(int i = length-1;i>=pos+str.length();i--) {
value[i] = value[i-str.length()];
}
int j=0;
for(int i = pos;i<pos+str.length();i++)
value[i] = str.toCharArray()[j++];
}
@Override
public void delete(int start) {
// TODO Auto-generated method stub
delete(start,length);
}
@Override
public void delete(int start, int end) {
// TODO Auto-generated method stub
if(start<0)
return;
if(start>=length)
return;
if(end>length)
return;
if(end<0)
return;
if(start>=end)
return;
while(end<length) {
value[start++] = value[end++];
}
length = length - end +start;
}
@Override
public void reverse() {
// TODO Auto-generated method stub
for(int i =0;i<length/2;i++) {
char temp = value[i];
value[i] = value[length-i-1];
value[length-i-1] = temp;
}
}
@Override
public int length() {
// TODO Auto-generated method stub
return length;
}
public String toString(){
char[] realValue = new char[length];
for(int i = 0;i<length;i++) {
realValue[i] = value[i];
}
return new String(realValue);
}
private static String randomString(int len) {
String pool = "";
for(short i = '1';i<='9';i++) {
pool +=(char) i;
}
for(short i = 'A';i<='Z';i++) {
pool +=(char) i;
}
for(short i = 'a';i<='z';i++) {
pool +=(char) i;
}
char cs[] = new char[len];
for(int i=0;i<len;i++) {
int dex =(int) (Math.random()*pool.length());
cs[i] = pool.charAt(dex);
}
String result = new String(cs);
return result;
}
public static void main(String[] args) {
int total = 5000000;
String s = randomString(10);
StringBuffer sb = new StringBuffer();
MyStringBuffer msb = new MyStringBuffer();
long start = System.currentTimeMillis();
for(int i=0;i<total;i++) {
msb.append(s);;
}
long end = System.currentTimeMillis();
System.out.printf("使用自己开发的连接+的方式,连接%d次,耗时%d毫秒%n",total,end-start);
start = System.currentTimeMillis();
for(int i=0;i<total;i++) {
sb.append(s);
}
end = System.currentTimeMillis();
System.out.printf("使用StringBuffer连接+的方式,连接%d次,耗时%d毫秒%n",total,end-start);
}
}
2.2唯一化(无序向量去重)
package Chap2;
/*
* 无序向量去重操作
* 复杂度O(n2)*/
import java.util.Arrays;
public class disorderDT {
public static void main(String[] args) {
int[] data = new int[] {1,4,4,2,3,3,7,6,1};
System.out.println(Arrays.toString(dedup(data)));
}
private static int[] dedup(int[] data) {
int oldsize = data.length;
int rank = 1;
boolean find = false;
while(rank<oldsize) {
for(int i = 0 ;i<rank;i++) {
if(data[i]==data[rank]) {
find = true;
oldsize -= 1;
break;
}
}
if(find) {
find = false;
data = remove(data,rank);
}else {
rank++;
}
}
return data;
}
public static int[] remove(int[] a,int i) {
int len = a.length;
int[] b =new int[len-1];
System.arraycopy(a, 0, b, 0, i);
System.arraycopy(a, i+1, b, i,len-i-1);
return b;
}
}
2.3唯一化(有序向量去重)
package Chap2;
/*
*有序数组唯一化 复杂度O(n)*/
import java.util.Arrays;
public class Dedup {
public static void main(String[] args) {
int[] data = new int[] {1,1,1,4,4,5,5,5,5,6,7,7,7,8,8};
System.out.println(Arrays.toString(dedup(data)));
}
private static int[] dedup(int[] data) {
int oldsize = data.length;
int i = 0;
int j = 0;
while(++j<oldsize) {
if(data[i]!=data[j])
data[++i] = data[j];
}
int[] dt = new int[i+1];
System.arraycopy(data, 0, dt, 0,i+1);
return dt;
}
}
2.4有序向量的二分查找(版本A)
package Chap2;
/*
* 查找长度:进入左侧只判断1次,进入右侧,需判断两次,从中间开始划分
* 最小查找时间O(1),时间复杂度O(log n),但if判断条件与时间分配不平衡
* 使用Fibonacci查找会更平衡*/
public class BinaryA {
public static void main(String[] args) {
int[] data = new int[] {1,2,3,4,5,7,8,8,8,10};
int res = binSearchA(data,8,0,data.length);
System.out.println(res);
}
public static int binSearchA(int[] data, int e,int lo,int hi) {
while(lo<hi) {
int mi = (lo+hi)>>1;
if(e<data[mi]) {
hi = mi;
}else if(data[mi]<e) {
lo = mi+1;
}else {
return mi;
}
}
return -1;
}
}
2.5有序向量二分查找(版本B)
package Chap2;
/*
* 只使用一次判断语句
* 但不可能一次就能找出该值e
* 但更加均衡*/
public class BinaryB {
public static void main(String[] args) {
int[] data = new int[] {1,2,3,4,5,7,8,8,8,10};
int res = binSearchB(data,9,0,data.length);
System.out.println(res);
}
public static int binSearchB(int[] data, int e,int lo,int hi) {
while(1<(hi-lo)) {
int mi = (lo+hi)>>1;
if(e<data[mi])
hi = mi;
else
lo = mi;
}
return (e==data[lo])?lo:-1;
}
}
2.6有序向量二分查找(版本C)
package Chap2;
/*
* 增加语义约定:返回不大于e的最后一个元素
* 多个元素命中,返回最靠后的秩
* 失败时,返回小于e的最大值者*/
public class BinaryC {
public static void main(String[] args) {
int[] data = new int[] {1,2,3,3,3,4,5,7,8,8,8,10};
int res = binSearchC(data,3,0,data.length);
System.out.println(res);
}
public static int binSearchC(int[] data, int e,int lo,int hi) {
while(lo<hi) {
int mi = (lo+hi)>>1;
if(e<data[mi])
hi = mi;
else
lo = mi+1;
}
return --lo;
}
}
2.7冒泡排序-改进版
但最坏情况下,时间复杂度仍然为O(n2)
package Chap2;
import java.util.Arrays;
public class Bubblesort {
public static void main(String[] args) {
int[] A = new int[] {2,3,1,8,9,6,12,14,16};
int lo = 0;
int hi = A.length;
while(lo<(hi = bubblesort(A,lo,hi)));
System.out.println(Arrays.toString(A));
}
public static int bubblesort(int[] A,int lo,int hi) {
int last = lo;
while(++lo<hi) {
if(A[lo-1]>A[lo]) {
last = lo;
int swamp = A[lo-1];
A[lo-1] = A[lo];
A[lo] = swamp;
}
}
return last;
}
}
2.8二路归并排序
时间复杂度O(nlogn),我可太讨厌写递归了。
package Chap2;
import java.util.Arrays;
public class Merge {
public static void main(String[] args) {
int[] A = new int[] {9,8,7,6,5,4,3,2,1};
mergesort(A,0,A.length);
System.out.println(Arrays.toString(A));
}
public static void mergesort(int[] A ,int lo ,int hi) {
if((hi-lo)<2)
return;
int mi = (hi+lo)>>1;
mergesort(A,lo,mi);
mergesort(A,mi,hi);
merge(A,lo,mi,hi);
}
public static void merge(int[] A,int lo,int mi,int hi) {
int lb = mi-lo;
int lc = hi-mi;
int[] B = new int[lb];
int[] C = new int[lc];
for(int i = 0;i<lb;i++)
B[i] = A[lo+i];
for(int i = 0;i<lc;i++)
C[i] = A[mi+i];
int ranka = lo;
int rankb = 0;
int rankc = 0;
for(;(rankb<lb)||(rankc<lc);) {
if((rankb<lb)&&(lc<=rankc||(B[rankb]<=C[rankc])))
A[ranka++] = B[rankb++];
if((rankc<lc)&&(lb<=rankb||(B[rankb]>C[rankc])))
A[ranka++] = C[rankc++];
}
System.out.println(Arrays.toString(A));
}
}