数组常见算法

一、数组排序(冒泡排序)

        1.冒泡排序是一种简单的排序算法,它重复地访问要排序的数列,依次比较相邻的两个元素,小(大)在前,如果顺序错误,则交换两个元素。这个步骤不断重复至没有元素再需要交换,也就是说该数列已经排序完成。

        2.冒泡排序的基本思路可以概括为以下几步:
           (1)从第一个元素开始,依次比较相邻的两个元素,小(大)在前,如果顺序错误就交换它们。
           (2)继续比较下一对相邻元素,直到最后一个元素,这样一轮比较下来,最大(小)的元素就会沉到数组的末尾。
           (3)重复以上步骤,每次比较都会使得未排序部分的最大元素沉到末尾,直到整个数组排序完成。

       总共比较N-1轮,每轮比较N-1-i次,N为数组的长度。但是为了提高算法的效率,对代码进行了优化:boolean isSorted=true;。当数组处于有序状态时,排序过程可提前结束。

       3. 冒泡排序是一种稳定的排序算法,但是在实际应用中由于其复杂度较高,通常不适用于大型数据集的排序。

import java.util.Arrays;

public class BubbleSort {
	public static void main(String[] args) {
		int[] n1= {31,7,54,86,2,64,34,5,10};    //无序数组
		System.out.println("原数组:"+Arrays.toString(n1));
		int counter=0;
		for(int i=0,n=n1.length;i<n-1;i++) {
			boolean isSorted=true;    //默认有序
			for(int k=0;k<n-1-i;k++) {
				counter++;
				if(n1[k]>n1[k+1]) {
					n1[k]=n1[k]^n1[k+1];
					n1[k+1]=n1[k]^n1[k+1];
					n1[k]=n1[k]^n1[k+1];
					isSorted=false;
					//System.out.println(Arrays.toString(n1));
				}
			}
			if(isSorted) {
				break;
			}
		}
		System.out.println("总共比较次数:"+counter);
		System.out.println("有序数组:"+Arrays.toString(n1));
	}

}

输出结果为:

原数组:[31, 7, 54, 86, 2, 64, 34, 5, 10]
总共比较次数:35
有序数组:[2, 5, 7, 10, 31, 34, 54, 64, 86]

二、无序数组查找        

        无序查找通常指的是在一个无序的数组或集合中查找指定元素的过程。常见的无序数组查找方法有调用二分查找算法、单指针查找,双指针查找。

1.调用二分查找算法

        使用二分查找算法的数组必须是有序数组,先调用Arrays.sort()方法对数组进行排序,然后调用Arrays.binarySearch()方法进行二分查找。

2.单指针查找

        使用遍历查找:对该无序数组进行遍历,将数组中的每个元素与目标元素进行比较。

3.双指针查找

        从数组的头部和尾部同时开始遍历,使用两个下标,将数组中的每个元素与目标元素进行比较,比单指针查找速率高。        

import java.util.Arrays;

public class UnorderArraySearch {
	public static void main(String[] args) {
		
		int[] n1 = { 31, 7, 54, 86, 2, 64, 34, 5, 10 };// 无序数组
		int target = 54;    //目标元素
		int index = -1;    //如果不存在目标元素,返回-1

		//方法1:调用二分查找算法
		Arrays.sort(n1);//先排序
		int ret=Arrays.binarySearch(n1, target);
		System.out.println(ret);

		//方法2:单指针查找(遍历查找)
		for(int i=0;i<n1.length;i++) {
			if(n1[i]==target) {
				index=i;
				break;
			}
		}
		System.out.println(index);
		

		// 方法3:双指针查找
		for (int i = 0, k = n1.length - 1; i <= k; i++, k--) {
			if (n1[i] == target) {
				index = i;
				break;
			}
			if (n1[k] == target) {
				index = k;
				break;
			}
		}
		System.out.println(index);
	}
}

输出结果为:

2

三、有序数组查找

    实现二分查找算法的步骤如下:

        (1)初始化查找范围:设置两个指针 low 和 high 分别指向数组的起始位置和结束位置。
        (2)进入循环:在一个 while 循环中,不断缩小查找范围直到找到目标元素或者确定目标元素不在数组中。
        (3)计算中间位置:计算中间位置 mid,可以使用 mid =(low+high)>>1;
        (4)比较中间元素:将目标元素与中间位置的元素进行比较。
        (5)调整查找范围:根据比较结果,调整指针 low 和 high 的位置,缩小查找范围。
        (6) 循环终止条件:当 low 大于 high 时,表示整个数组已经查找完毕,如果此时还没有找到目标元素,则说明目标元素不在数组中。

        这个算法要求数组是有序的,因此在实际应用中,可以先对无序数组进行排序,然后再使用二分查找算法。

public class BinarySearch {
	public static void main(String[] args) {
		int[] n= {1,2,3,4,5,6,7,8,9};
		int target=9;
		int ret=binary(n,target);
		System.out.println(ret);
	}
	
	public static int binary(int[] n,int target) {
		int low=0,high=n.length-1;
		while(low<=high) {
			int mid=(low+high)>>1;
			if(n[mid]==target) {
				return mid;
			}else if(n[mid]>target) {
				high=mid-1;
			}else if(n[mid]<target) {
				low=mid+1;
			}
		}
		//找不到返回-1
		return -1;
	}
}

输出结果为:

8

四、数组乱序

     实现数组乱序的的步骤:

        (1)从数组尾部开始,使用for循环遍历数组中的每个元素

        (2)调用Math.random()方法产生随机数作为随机下标,产生随机数的范围为0~遍历元素的下标值

        (3)遍历时,每个元素与产生的随机的下标指向的元素进行交换,直至每个元素都进行一次交换

        以上为内层for循环的作用,外层for循环的作用是控制乱序的次数。

public class Disorder{
	public static void main(String[] args) {
		int[] arr = { 1, 2, 3, 4, 5, 6 };
		System.out.println("原数组:"+Arrays.toString(arr));
		for (int k = 1; k <= 3; k++) {// 乱序次数
			for (int i = arr.length - 1; i > 0; i--) {
				int rand = (int) (Math.random() * i);
				arr[rand] = arr[rand] ^ arr[i];
				arr[i] = arr[rand] ^ arr[i];
				arr[rand] = arr[rand] ^ arr[i];
			}
		}
		System.out.println("乱序后:"+Arrays.toString(arr));
	}

}

输出结果为:

原数组:[1, 2, 3, 4, 5, 6]
乱序后:[6, 3, 2, 5, 4, 1]

五、数组旋转

    数组旋转分为向右旋转和向左旋转

        1.向右旋转

          (1)有两层循环,外层循环控制乱序的次数,内层循环控制旋转的方向,每次向右旋转1位

          (2)从尾部开始(逆序),将尾元素不断与前一位元素交换至数组头部

        2.向左旋转

          (1)有两层循环,外层循环控制乱序的次数,内层循环控制旋转的方向,每次向左旋转1位

          (2)从头部开始(顺序),将尾元素不断与后一位元素交换至数组尾部

public class Rotate {

	public static void main(String[] args) {
		int[] n= {1,2,3,4,5,6,7,8};
		System.out.println("原数组:"+Arrays.toString(n));
		right(n);
		left(n);
        
	}
	
	public static void left(int[] n) {
		//左旋
		for(int k=1;k<=3;k++) {
			for(int i=0;i<n.length-1;i++) {
				n[i]=n[i]^n[i+1];
				n[i+1]=n[i]^n[i+1];
				n[i]=n[i]^n[i+1];
			}
		}
		System.out.println("右旋后:"+Arrays.toString(n));
	}

	public static void right(int[] n) {
		//右旋
		for(int k=1;k<=3;k++) {
			for(int i=n.length-1;i>0;i--) {
				n[i]=n[i]^n[i-1];
				n[i-1]=n[i]^n[i-1];
				n[i]=n[i]^n[i-1];
			}
		}
		System.out.println("左旋后:"+Arrays.toString(n));
	}
}

输出结果为:

原数组:[1, 2, 3, 4, 5, 6, 7, 8]
左旋后:[6, 7, 8, 1, 2, 3, 4, 5]
右旋后:[1, 2, 3, 4, 5, 6, 7, 8]

  • 36
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值