您的位置:首页 > 编程语言 > Java开发

常见算法的java实现代码(持续更新中)

2016-09-16 18:38 495 查看
1.快速排序算法

快速排序算法的原理是:假设要排序的数组是A[1]……A
,首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一躺快速排序,然后递归该算法,就可以将数组快速排序,常用实现方法是这样的:

private int[] bArray = new int[]{50,72,36,9,18,29,31,61,519,11};

int [] result = quickSort(bArray,0,bArray.length-1);

private int[] quickSort(int[] array,int i,int j){
// 左端小于右端时进行排序操作
if(i < j){
// 以数组第一个值为标准值
int key = array[i];
int low = i;
int high = j;
// 当low小于high时开始循环
while(low < high){
//循环找到array[high] > key,没有则指针左移
while(low < high && array[high] > key){
high--;
}
// 可能已经结束,避免死循环,将小于标准值的右端的数放到左端
if(low < high)
array[low++] = array[high];

//循环找到array[low] < key,没有则指针右移
while(low < high && array[low] < key){
low++;
}
// 可能已经结束,避免死循环,将大于标准值的右端的数放到右端
if(low < high)
array[high--] = array[low];
}
//  当左右端的循环结束,循环结束的位置即是key的位置
array[low] = key;
//  递归排序此次标准值左端的数据
quickSort(array,i,low-1);
// 递归排序此次标准值右端的数据
quickSort(array,low+1,j);
}

return array;
}

2.堆排序

堆排序算法的原理是:1.将初始数组R[]构造成大顶堆

      2.将堆顶R[0]与堆底R
互换,然后重新把堆调整成符合标准的大顶堆

      3.之后将堆底剔除,然后重复2的操作直到将R[]中的除堆顶全部排完 其实现代码为:

大顶堆的标准为:任何一非叶节点的关键字不小于其左右孩子节点的关键字

//    构建大顶堆
public void createMaxdHeap(int[] data, int lastIndex) {
for (int i = (lastIndex - 1) / 2; i >= 0; i--) {
// k为当前节点的上一级结点
int k = i;
// 此while存在的意义在于如果子节点比当前结点大时互换后需要重新排序
while (2 * k + 1 <= lastIndex) {
// biggerIndex总是记录较大节点的值,先赋值为当前判断节点的左子节点
int biggerIndex = 2 * k + 1;
// 判断当前节点的子节点是否存在
if (biggerIndex < lastIndex) {
// 判断左右两个节点那个大,选取大的那个节点与父节点比较
if (data[biggerIndex] < data[biggerIndex + 1]) {
biggerIndex++;
}
}
if (data[k] < data[biggerIndex]) {
// 若当前节点值比子节点最大值小,则交换2者得值,交换后将biggerIndex值赋值给k
swap(data, k, biggerIndex);
k = biggerIndex;
} else {
break;
}
}
}
}

// 交换两个位置的值
public void swap(int[] data, int i, int j) {
if (i == j) {
return;
}
data[i] = data[i] + data[j];
data[j] = data[i] - data[j];
data[i] = data[i] - data[j];
}

3.归并排序

归并排序是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。我自己先实现了合并的这部分:

1.先申请空间,构建一个大小为两个有序数组大小之和的的数组;

2.设定三个指针,分别指向三个数组;

3.比较两个有序数组指针指向的值,取最小值放在新的数组中;

4.将指针右移然后继续3的操作;其实现代码为:

private int[] mArray1= new int[]{1,5,17,38};
private int[] mArray2= new int[]{2,4,12};

merge(mArray1,mArray2);

private void merge(int[] array1,int[] array2){
int length = array1.length+array2.length;
int[] newArray = new int[length];
int i = 0;
int j = 0;
int z = 0;
//  当两个数组的指针都不超过数组大小时进行循环,最后会循环到只剩下一个数组的值没添加到新数组,或者都添加进新数组
while (i<= array1.length-1 && j <=array2.length-1){
//  取指针指向的最小值,将之添加到新数组
if(array1[i] <= array2[j]){
newArray[z++] = array1[i++];
}
if(array1[i] > array2[j]){
newArray[z++] = array2[j++];
}
}
//  当只剩下array1里的值没有放进新建数组中时,将array1的值全部放进新建数组中
while (i<= array1.length-1){
newArray[z++] = array1[i++];
}
// 当只剩下array2里的值没有放进新建数组中时,将array2的值全部放进新建数组中
while (j <=array2.length-1){
newArray[z++] = array2[j++];
}

}


[b]4.二分法查找[/b]

二分法查找。。。应该不用我解释原理吧。。话说我以前写html的时候要是有bug就用二分法查找来着

但是要注意的是使用二分法的前提是
查找数组时有序数组,然后下面是我写的查询方法,

//    参数待查找的数组,待查找的数
private boolean binarySearch(int[] data,int number){
int left = 0;
int mid = (data.length-1)/2;
int right = data.length-1;
//  当待查找的数大于最大或者小于最小时直接跳出
if(number < data[left] || number > data[right])
return false;
//  当数字在数组范围内时
while (left <= mid && mid <= right){
//  循环至三个节点进行判断,成功就跳出
if(number == data[left]) return true;
if(number == data[mid]) return true;
if(number == data[right]) return true;
//  进行循环时会出现left = mid的情况,即right =left + 1 在这里进行判断,防止死循环
if(left == mid || mid == right){
if(number == data[right] || number == data[left]) return true;
else return false;
}
//  当查找数在left与mid之间时,把right赋值为mid,mid重新赋值
if (number > data[left] && number < data[mid]){
right = mid;
mid = (right + left)/2;
}
// 当查找数在mid与right之间时,把left赋值为mid,mid重新赋值
if (number >data[mid] && number <= data[right]){
left = mid;
mid = (right + left)/2;
}
}
return false;
}

由于上面的代码是我写的所以逻辑上肯定是有多余的地方的,刚刚看了一下别人的代码,他们是这样写的

// 参数待查找的数组,待查找的数
private boolean binarySearch(int[] data,int number){
int left = 0;
int right = data.length-1;
// 当数字在数组范围内 开始循环
while (left <= right){
int mid = (right + left)/2;
// 当查找数在left与mid之间时,最右指针移至mid-1
if (number < data[mid]){
right = mid-1;
}
// 当查找数在mid与right之间时,最左指针移至mid+1
else if (number > data[mid]){
left = mid+1;
// 出现相等情况下,返回true
}else {
return true;
}
}
return false;
}

简洁的地方在于把我用来规避死循环的那些情况都去掉了 他在最后一个else里判断数组是否含有目标数字。。我用了三个。。当然最大的不同在于right = mid-1 这种写法,一开始没想到这种写法的原因是害怕,这样会把此刻大于data[mid-1]小于data[mid]的值落下,其实是没有必要的,因为如果他此时是这种情况的话,就会一直进入else if里直到left>right 退出循环
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: