1.冒泡排序
//冒泡排序
/*
具体思路:
(1) 整个数列分成两部分:前面是无序数列,后面是有序数列
(2) 初始状态下,整个数列都是无序的,有序数列是空
(3) 如果一个数列有n个元素,则至多需要n-1趟循环才能保证数列有序
(4) 每一趟循环可以让无序数列中最大数排到最后,(也就是说有序数列的元素个数增加1)
(5) 每一趟循环都从数列的第一个元素开始进行比较,依次比较相邻的两个元素,比较到无序数列的末尾即可(而不是数列的末尾)
(6) 如果前一个大于后一个,交换
*/
public class Test02 {
public static void main(String[] args) {
int[] a ={30,25,40,15,100,65,20}; //定义数组并给出对应的值
int count=0; //定义一个统计次数的变量
for (int j = 0; j < a.length-1; j++) { //外层循环控制是的几趟,并且长度-1,下标是从0开始的,并且长度超出就会跳出循环
//内层循环是控制比较的次数,并且长度-1,下标是从0开始的
//当最外层循环执行完之后,就-j,表示这趟已经执行完了,再不需要挨个值和后面一个值比较,比较节省空间
boolean flag = true; //定义一个boolean为true,表示顺序已经排好
for (int i = 0; i <a.length-1-j; i++) {
count++; //每次进入循环就+1,统计走了多少次
if (a[i]>a[i+1]){ //判断第一个下标的数组的值和第二个下标的数组的值做判断,数组的值大于就进入判断进行值交换,否则不进入判断,直接跳出循环,以此类推
int temp; //定义中间变量
temp=a[i]; //a[1]=15,将这个15赋值给temp
a[i]=a[i+1]; //a[2]=4,将这个4赋值给下标a[1],a[2]现在的值为4
a[i+1]=temp; //将15这个数赋值给a[2],a[2]现在的值为15,然后都是以此类推!
flag=false; //false,表示顺序没有排好,就要进行比较
}
}
if(flag){ //判断里面的循环是否已经排好了顺序,排好了,就直接跳出层循环,就不需要再比较
break;
}
System.out.println(Arrays.toString(a)); //快速遍历
}
System.out.println(count); //统计的次数
}
}
2.选择排序
//选择排序
/*
具体思路:
(1) 整个数列分成两部分:前面是有序数列,后面是无序数列
(2) 初始状态下,整个数列都是无序的,有序数列是空
(3) 一共n个数,需要n-1趟循环(一趟都不能少)
(4) 每比较完一趟,有序数列数量+1,无序数列数量-1
(5) 每趟先假设无序数列的第1个元素(整个数列的第i个元素)是最小的,让当前的最小数,从第i+1个元素开始比较,一直比较到最后一个元素。如果发现更小的数,就假设当前数是最小数。
(6) 一趟比较完后,将发现最小数和无序数列的第一个数交换(如果最小数不是无序数列的第一个数)
*/
public class Test02 {
public static void main(String[] args) {
int[] a ={30,25,40,15,100,65,20}; //定义一个数组并赋值
int count=0;
for (int j = 0; j <a.length-1 ; j++) { //外层循环比较的是趟数
int minIndex=j; //默认下标为0的值为最小值进行比较
for (int i = minIndex+1; i <a.length; i++) { //默认每次循环的最小值下标+1
//这个判断主要是交换下标
if (a[minIndex]>a[i]){ //将默认最小值索引为a[0]=30和a[1]=25做比较,大于进入判断条件,否则不进入,结果大于,以此类推
minIndex=i; //把最小值变量替换成指定下标,就好比15的下标和30的下标交换位置
}
count++;
}
//这个判断主要是交换值的
if (minIndex!=j){ //如果不等于0,就说明下标进行交换了,然后进行入判断条件
int temp; //定义一个中间变量
temp=a[j]; //a[0]=30赋值给temp,temp现在的值为30
a[j]=a[minIndex]; //a[3]的值15赋值给a[0]=30,现在a[0]=15,a[0]和a[3]的值都为15
a[minIndex]=temp; //将30赋值给a[3],所以现在的a[3]的值为30
}
System.out.println(Arrays.toString(a));
}
System.out.println(count);
}
}
3.插入排序
//快速排序
/*
具体思路:
1. 选择要排序数组的左边第一个元素作为基准
2. 然后从要排序数组的最右边开始进行检索,找比基准数小的,找到后就先停止检索
3. 然后从要排序数组的最左边开始进行检索,找比基准数大的,找到后就先停止检索
4. 将上面两个找到的元素进行交换
5. 交换完后,接着使用同样的方式进行检索
6. 当左边索引 和 右边索引相等时,停止检索,并且将基准数和相等的这个索引元素进行交换
7. 然后发现,在相遇的这个位置,左边的元素都比基准数小,右边 的元素都比基准数大
接下来,接着分别对相遇索引的左边 和 相遇索引的右边 进行同样的快速排序操作!
*/
public class Test01 {
public static void main(String[] args) {
int[] arr={33,17,9,88,77,39}; //定义一个数组长度为6,并且赋了值
bb(arr,0,arr.length-1); //定义传递的参数和左右下标,传递的参数分别为:数组变量,左侧长度为0,右侧长度为总长度5
System.out.println(Arrays.toString(arr)); //快速遍历数组
}
public static void bb(int[] arr,int left,int right){ //定义一个静态方法,分别接受传过来的参数arr={33,17,9,88,77,39},left:0,right:5
//如果左侧下标比右侧下标大 直接停止即可
if (left>right){ //判断最左侧的数是否大于右侧,大于进入判断语句,并返回bb方法,小于就不进入
return;
}
int l=left; //将左侧下标0赋值给l
int h=right; //将右侧下标5赋值给h
int base=arr[l]; //指定数组a[0]下标这个数的值33赋值给base
while(l<h){ //循环的条件,如果左侧长度小于右侧长度,就进入循环,否则不进入
while (arr[h]>=base&&l<h){ //右侧的值如果大于基数时右侧下标--
h--;
}
//如果出了循环证明在右侧找到了比基数小的数
if (l<h){
arr[l]=arr[h]; //把右侧的值赋值给左侧的位置
}
//左侧判断的实现 左侧的数字比基数小 这个时候把左侧的下标++
while (arr[l]<=base&&l<h){
l++;
}
//如果出了while循环证明在左侧找到了比基数大的值
if (l<h){
arr[h]=arr[l]; //把左侧的值赋值给右侧
}
//如果出现等于情况 我们就把基数直接赋值给指定下标
if (l>=h){
arr[l]=base;
}
}
//左侧的比较
bb(arr, left, l-1);
//右侧比较
bb(arr,l+1,right);
}
}
4.快速排序
//快速排序
/*
具体思路:
1. 选择要排序数组的左边第一个元素作为基准
2. 然后从要排序数组的最右边开始进行检索,找比基准数小的,找到后就先停止检索
3. 然后从要排序数组的最左边开始进行检索,找比基准数大的,找到后就先停止检索
4. 将上面两个找到的元素进行交换
5. 交换完后,接着使用同样的方式进行检索
6. 当左边索引 和 右边索引相等时,停止检索,并且将基准数和相等的这个索引元素进行交换
7. 然后发现,在相遇的这个位置,左边的元素都比基准数小,右边 的元素都比基准数大
接下来,接着分别对相遇索引的左边 和 相遇索引的右边 进行同样的快速排序操作!
*/
public class Test01 {
public static void main(String[] args) {
int[] arr={33,17,9,88,77,39}; //定义一个数组长度为6,并且赋了值
bb(arr,0,arr.length-1); //定义传递的参数和左右下标,传递的参数分别为:数组变量,左侧长度为0,右侧长度为总长度5
System.out.println(Arrays.toString(arr)); //快速遍历数组
}
public static void bb(int[] arr,int left,int right){ //定义一个静态方法,分别接受传过来的参数arr={33,17,9,88,77,39},left:0,right:5
//如果左侧下标比右侧下标大 直接停止即可
if (left>right){ //判断最左侧的数是否大于右侧,大于进入判断语句,并返回bb方法,小于就不进入
return;
}
int l=left; //将左侧下标0赋值给l
int h=right; //将右侧下标5赋值给h
int base=arr[l]; //指定数组a[0]下标这个数的值33赋值给base
while(l<h){ //循环的条件,如果左侧长度小于右侧长度,就进入循环,否则不进入
while (arr[h]>=base&&l<h){ //右侧的值如果大于基数时右侧下标--
h--;
}
//如果出了循环证明在右侧找到了比基数小的数
if (l<h){
arr[l]=arr[h]; //把右侧的值赋值给左侧的位置
}
//左侧判断的实现 左侧的数字比基数小 这个时候把左侧的下标++
while (arr[l]<=base&&l<h){
l++;
}
//如果出了while循环证明在左侧找到了比基数大的值
if (l<h){
arr[h]=arr[l]; //把左侧的值赋值给右侧
}
//如果出现等于情况 我们就把基数直接赋值给指定下标
if (l>=h){
arr[l]=base;
}
}
//左侧的比较
bb(arr, left, l-1);
//右侧比较
bb(arr,l+1,right);
}
}
5.递归
//递归算法
//递归自己调用自己--递归的出现就是代替循环
//递归一定要注意,必须指定可以让程序停止的条件
public class Test01 {
public static void main(String[] args) {
int a = aa(6); //调用静态方法,赋值,并且将返回值6赋值给a
System.out.println(a);
}
public static int aa(int n){
int result;
if (n==1){ //停止条件 如果n等于1,就直接返回1
result=1;
}else {
result=n*aa(n-1); //进行递归运算调用之前每一次结果
}
return result; //把结果返回
}
}
6.二分查找
//二分查找
/*
具体思路:
折半查找又称为二分查找,这种查找方法需要待查的查找表满足两个条件:
首先,查找表必须使用顺序存储结构;
其次,查找表必须按关键字大小有序排列。
*/
public class Test04 {
public static void main(String[] args) {
int[] arr ={1,2,3,4,5,6,7,8,9,10};
int index = getIndex(arr, 0, arr.length - 1, 2); //传参 数组变量 左侧开始下标0 数组的长度9 查询的目标
System.out.println("目标数字的下标为:"+index); //输出返回值
}
public static int getIndex(int[] arr,int start,int end,int tag){ //定义一个方法参数分别为数组,左侧开始下标,右侧结束下标,查询的目标
if (arr==null||arr.length==0){ //判断数组是否为空
return -1;
}
while (start<=end){ //左侧的下标要小于等于右侧的下标
int mid=(start+end)/2; //中间的下标等于两侧的索引相加除以2,求出中间变量的下标
if (tag==arr[mid]){ //查询目标的值等于中间变量索引的值,等于就直接返回
return mid; //
}else if (tag>arr[mid]){ //查询目标的值大于中间变量的值,左侧下标就往中间值右侧+1
start=mid+1;
}else {
end=mid-1; //最后不满足上面两个条件,右侧下标就往中间值左侧-1
}
}
return -1; //数组里面没有查询目标的数时,就返回-1
}
}