数据结构与算法基础

1、数据结构

存储数据的不同方式。

2、算法

同一问题的不同解决方法。(算法往往是针对特定数据结构的。)

算法的优劣

时间复杂度:随着问题规模的变化而时间变化的规律。
空间复杂度:随着问题规模的变化而空间变化的规律。

3、 Big O

时间-问题(数据)规模

  • 不考虑必须要做的操作
    循环、赋初值、程序初始化……
  • 不考虑常数项
  • 不考虑低次项

常见排序列表

序号中文名称英文名称平均时间复杂度最坏时间复杂度最好时间复杂度空间复杂度稳定性
1选择排序Selectionn2n2n21N
2冒泡排序Bubblen2n2n1Y
3*插入排序Insertionn2n2n1Y
4*堆排序Heapn log2nn log2nn log2n1N
5希尔排序Shelln1.3n2n1N
6*归并排序Mergen log2nn log2nn log2nnY
7*快速排序Quickn log2nn2n log2nlog2nN
8桶排序Buckeln + kn2nn + kY
9计数排序Countingn + kn + kn + kn + kY
10基数排序Radixn * kn * kn * kn + kY

(注意Y:稳定,N:不稳定。)

在这里插入图片描述

如何编写算法程序

  1. 有简单到复杂
    验证一步走一步
    多打印中间结果
  2. 先局部后整体
    没思路时先细分
  3. 先粗糙后精细
    变量更名
    语句合并
    边界处理

简单排序

1、选择排序

package Tests;

public class Test1 {
/*
 * 选择排序
 * 
 * */
	public static void main(String[] args) {
		int[] arrays = { 4, 6, 7, 2, 8, 1, 9, 3, 5 };
//		排序前
		System.out.println("排序前:");
		for (int i = 0; i < arrays.length; i++) {
			System.out.print(arrays[i] + " ");
		}
//		long star = System.currentTimeMillis();
		for (int j = 0; j < arrays.length; j++) {
//		1、线找到最小值的下标
			int min = j;
			for (int i = j + 1; i < arrays.length; i++) {
				if (arrays[i] < arrays[min]) {
					min = i;
				}
			}
//		2、将最小值的下标与第一个元素进行交换位置
			int temp = arrays[j];
			arrays[j] = arrays[min];
			arrays[min] = temp;
		}
//		long end = System.currentTimeMillis();
		System.out.println("\n排序后:");
		for (int i = 0; i < arrays.length; i++) {
			System.out.print(arrays[i] + " ");
		}
//		System.out.println("\nusing time:" + (end - star));
	}

}
package com.gxd.dao;

public class SelectSort {
    public static void main(String[] args) {
        int[] arr = {2,4,6,8,9,5,3,1};
        sort(arr);
        System.out.println("***************");
        print(arr);
    }

    private static void print(int[] arr) {
        for (int i:arr) {
            System.out.print(i+",");
        }
        System.out.println();
    }

    private static void sort(int[] arr) {
        for (int i = 0; i < arr.length-1; i++) {
            int min = i;
            for (int j = i+1; j < arr.length; j++) {
                min = arr[min] > arr[j] ? j : min;
            }
            int temp = arr[i];
            arr[i] = arr[min];
            arr[min] = temp;
            print(arr);
        }
    }
}

//运行结果:
1,4,6,8,9,5,3,2,
1,2,6,8,9,5,3,4,
1,2,3,8,9,5,6,4,
1,2,3,4,9,5,6,8,
1,2,3,4,5,9,6,8,
1,2,3,4,5,6,9,8,
1,2,3,4,5,6,8,9,
***************
1,2,3,4,5,6,8,9,

选择排序(实现list集合)

package com.bennett.test1014;

import java.util.LinkedList;
import java.util.List;

/**
 * 选择排序(实现list集合)
 * @author bennett
 *
 */
public class SelectSortByList {
	public static void main(String[] args) {
//		System.out.println("hello world!");
		List<Integer> integers = new LinkedList<Integer>();
		integers.add(4);
		integers.add(7);
		integers.add(3);
		integers.add(8);
		integers.add(2);
		integers.add(9);
		integers.add(1);
		print(integers);
		System.out.println();
		SelectSortByList(integers);
		print(integers);
	}

	private static void SelectSortByList(List<Integer> integers) {
		for (int i = 0; i < integers.size(); i++) {
			int min = i;
			for (int j = i+1; j < integers.size(); j++) {
				if (integers.get(j) < integers.get(min)) {
					min = j;
				}
			}
			int temp = integers.get(i);
			integers.set(i, integers.get(min));
			integers.set(min, temp);
		}
	}

	private static void print(List<Integer> integers) {
		for (Integer integer : integers) {
			System.out.print(integer+" ");
		}
	}
}

对算法的时间/空间复杂度进行分析

验证算法——对数器

DataChecker.java

package Tests;

import java.util.Arrays;
import java.util.Random;

public class DataChecker {
	/*
	 * 第一步:创建随机数组
	 */
	static int[] getByRandomToArrays() {
//		1、创建一个随机数的对象
		Random r = new Random();
//		2、创建数组
		int[] arr = new int[20];
//		3、向数组中添加数组元素
		for (int i = 0; i < arr.length; i++) {
			arr[i] = r.nextInt(20);
		}
		return arr;
	}
	/*
	 * 第二步:系统的比较器与你的比较算法进行比较
	 * 
	 */

	static void check() {
		int[] arr1 = getByRandomToArrays();
//		拷贝一份随机数组
		int[] arr2 = new int[arr1.length];
		System.arraycopy(arr1, 0, arr2, 0, arr1.length);

//		使用系统的比较器进行数组的排序
		Arrays.sort(arr1);
//		使用你的排序算法进行排序
		SelectSort.sort(arr2);
		/*
		 * 第三步:进行数组元素之间的比较
		 *
		 */
		Boolean b = true;
		for (int i = 0; i < arr2.length; i++) {
//			if (arr1[i] != arr2[i])
//				b = false;
			b = arr1[i] != arr2[i] ? false:true;
		}
		System.out.println(b == true ? "righr" : "wrong");
//		return b;
	}
	
//	main()方法测试
	public static void main(String[] args) {
		check();
	}

}

注意:最好是在check()进行多次的比较,对你写的算法就更加可靠。

SelectSort.java
自己定义的排序算法

package Tests;

public class SelectSort {
	
	public static int[] sort(int[] arr3) {
		for (int i = 0; i < arr3.length; i++) {
			int min = i;
			for (int j = i + 1; j < arr3.length; j++) {
				min = arr3[j] < arr3[min] ? j : min;
			}
			int temp = arr3[i];
			arr3[i] = arr3[min];
			arr3[min] = temp;
		}
		return arr3;
	}

}

2、冒泡排序

//	冒泡排序1 
	public static void bubbleSort(int arr[]) {

		for (int i = 0; i < arr.length - 1; i++) {
			for (int j = 0; j < arr.length - 1 - i; j++) {
				if (arr[j] > arr[j + 1]) {
					int temp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = temp;
				}
			}
		}
	}

//	冒泡排序2 
	static void sort(int arr[]) {
		for (int i = arr.length - 1; i > 0; i--) {
			for (int j = 0; j < i; j++) {
				if (arr[j] > arr[j + 1]) {
					int temp = arr[j + 1];
					arr[j + 1] = arr[j];
					arr[j] = temp;
				}
			}
		}
	}

3、插入排序

package bennett.sortingAlgorithm;

public class InsertionSort {
    public static void main(String[] args) {
        int[] arrays = {5,3,6,8,1,7,9,4,2};
        System.out.println("排序前");
        print(arrays);
        sort(arrays);
        System.out.println("\n排序后");
        print(arrays);
    }

    static void sort(int[] arr) {
        for (int i = 0; i < arr.length; i++) {  //i最好从i=1开始,因为i=0时,内层循环不执行
            for (int j = i; j > 0; j--) {
                if (arr[j] < arr[j - 1]) {
                    swap(arr, j, j - 1);
                }
            }
 /*优化结构 
for (int j = i; j > 0 && arr[j] < arr[j - 1]; j--) {
                    swap(arr, j, j - 1);
            }
*/           
        }
    }
//问题:为什么arr.length时,排序后将会8变为4???
    static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    public static void print(int[] a) {
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i]);
        }
    }
}

非简单排序

1、希尔排序

package bennett.sortingAlgorithm;

public class ShellSort {
    public static void main(String[] args) {
        int[] arrays = {9,6,11,3,5,12,8,7,10,15,14,4,1,13,2};
        System.out.println("排序前");
        print(arrays);
        sort(arrays);
        System.out.println("\n排序后");
        print(arrays);
    }

    static void sort(int[] arr) {
//        version 1.0
//        shift + ctrl + /如下注释  。ctrl + / 每一个都用“//”注释
        /*for(int gap = 4; gap > 0;gap /= 2){
            for (int i = gap; i < arr.length; i++) {
                for (int j = i; j > gap - 1; j-= gap) {
                    if (arr[j] < arr[j - gap]) {
                        swap(arr, j, j - gap);
                    }
                }
            }
        }*/
//        version 2.0
//        希尔最开时就是使用二分的办法来进行分组
        /*for(int gap = arr.length / 2; gap > 0;gap /= 2){
            for (int i = gap; i < arr.length; i++) {
                for (int j = i; j > gap - 1; j-= gap) {
                    if (arr[j] < arr[j - gap]) {
                        swap(arr, j, j - gap);
                    }
                }
            }
        }*/
//        version 3.0
//        Kunth序列
//        h = 1; h = 3*h +1;
        int h = 1;
        while(h <= arr.length / 3){
            h = 3*h + 1;
        }
        for(int gap = h; gap > 0;gap = (gap - 1)/3){
            for (int i = gap; i < arr.length; i++) {
                for (int j = i; j > gap - 1; j-= gap) {
                    if (arr[j] < arr[j - gap]) {
                        swap(arr, j, j - gap);
                    }
                }
            }
        }
    }
    //问题:为什么arr.length时,排序后将会8变为4???
    static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    public static void print(int[] a) {
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i]+",");
        }
    }
}

2、快速排序(Quick Sort)

package bennett.sortingAlgorithm;

public class QuickSort {
    public static void main(String[] args) {
        int[] arr = {7,3,2,8,1,9,5,4,6};
        System.out.println("排序前");
        print(arr);
        sort(arr,0,arr.length - 1);
        System.out.println("\n排序后");
        print(arr);
    }

    public static void sort(int[] arr, int leftBound, int rightBound) {
        if (leftBound >= rightBound) return;
        int mid = partition(arr,leftBound,rightBound);
        sort(arr,leftBound,mid - 1);
        sort(arr,mid + 1,rightBound);
    }
    static int partition(int[] arr, int leftBound, int rightBound){
        int pivot = arr[rightBound];
        int left = leftBound;
        int right = rightBound - 1;

        while (left <= right){
            while (left <= right && arr[left] <= pivot) left ++;
            while (left <= right && arr[right] > pivot) right --;

//            System.out.println("left = "+left+" ;right = "+right);
            if (left < right) swap(arr,left,right);
        }

        swap(arr,left,rightBound);
        return left;
    }
    static void swap(int[] arr,int i,int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
    static void print(int[] arr){
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+",");
        }
    }
}

list集合进行快速排序

package com.bennett.test1013;

import java.util.ArrayList;
import java.util.List;

/**
 * @version:
 * @Description:对list集合进行快速排序
 * @author bennett
 * @date: 2021年10月13日 下午8:39:40
 */ 
public class QuickSortByList {
	public static void main(String[] args) {
		List<Integer> integers = new ArrayList<Integer>();
		integers.add(7);
		integers.add(3);
		integers.add(2);
		integers.add(8);
		integers.add(1);
		integers.add(9);
		integers.add(5);
		integers.add(4);
		integers.add(6);
		System.out.println("排序前");
		print(integers);
		sort(integers, 0, integers.size()-1);
		System.out.println("\n排序后");
		print(integers);
	}

	public static void sort(List<Integer> integers, int leftBound, int rightBound) {
		if (leftBound >= rightBound)
			return;
		int mid = partition(integers, leftBound, rightBound);
		sort(integers, leftBound, mid - 1);
		sort(integers, mid + 1, rightBound);
	}

	static int partition(List<Integer> integers, int leftBound, int rightBound) {
		int pivot = integers.get(rightBound);
		int left = leftBound;
		int right = rightBound - 1;

		while (left <= right) {
			while (left <= right && integers.get(left) <= pivot)
				left++;
			while (left <= right && integers.get(right) > pivot)
				right--;

			if (left < right)
				swap(integers, left, right);
		}

		swap(integers, left, rightBound);
		return left;
	}

	static void swap(List<Integer> integers, int i, int j) {
		int temp = integers.get(i);
		integers.set(i, integers.get(j));
		integers.set(j, temp);
	}

	static void print(List<Integer> integers) {
		for (Integer integer : integers) {
			System.out.print(integer+" ");
		}
	}
}

归并排序

package bennett.sortingAlgorithm;
//归并排序
public class MergeSort {
    public static void main(String[] args) {
//		1、数组初始化
        int[] arrays = {2,5,7,8,3,4,9};
        System.out.println("排序前");
        print(arrays);
        sort(arrays);
    }
    static void sort(int[] arr) {
        merge(arr);
    }
    static void merge(int[] arr){
        int mid = arr.length / 2;
        int[] temp = new int[arr.length];

        int i = 0;
        int j = mid + 1;
        int k = 0;
        while (i <= mid && j < arr.length){
            if (arr[i] <= arr[j]){
                temp[k] = arr[i];
                i++;
                k++;
            }else {
                temp[k] = arr[j];
                j++;
                k++;
            }
//            if...else...的优化
//            temp[k++] = arr[i] <= arr[j] ? arr[i++] : arr[j++];  //代码优化
        }
        while (i <= mid) temp[k++] = arr[i++];
        while (j < arr.length) temp[k++] = arr[j++];
        System.out.println("\n排序后:");
        print(temp);
    }
    // 2、打印数组元素
    public static void print(int[] a) {
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i]);
        }
    }
}

归并排序(优化)

package bennett.sortingAlgorithm;
//归并排序(优化)
public class MergeSort {
    public static void main(String[] args) {
//        1、数组元素初始化
        int[] arrays = {2,5,7,8,3,4,9};
        System.out.println("排序前");
        print(arrays);
        sort(arrays,0,arrays.length - 1);
        System.out.println("排序后");
        print(arrays);
    }
//    3、排序
    public static void sort(int[] arr,int left,int right) {
        if (left == right) return;
        int mid = left + (right - left)/2;//分成两半
        sort(arr,left,mid);//左边排序
        sort(arr,mid+1,right);//右边排序
        merge(arr,left,mid+1,right);//归并排序
    }
//  4、归并排序
    public static void merge(int[] arr,int leftPtr,int rightPtr,int rightBound){
        int mid = rightPtr - 1;
        int[] temp = new int[rightBound - leftPtr + 1];
        int i = leftPtr;
        int j = rightPtr;
        int k = 0;
        while (i <= mid && j <= rightBound){
            temp[k++] = arr[i] <= arr[j] ? arr[i++] : arr[j++];  //代码优化
        }
        while (i <= mid) temp[k++] = arr[i++];
        while (j <= rightBound) temp[k++] = arr[j++];
        for(int n = 0;n < temp.length;n++) arr[leftPtr+n] = temp[n];
    }
//  2、打印数组元素
    public static void print(int[] a) {
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i]);
        }
        System.out.println();
    }
}

4、创建算法介绍

回溯法(Backtracking)

n皇后问题描述为:在一个nxn的棋盘上摆放n个皇后,要求任意两个皇后不能冲突,即任意两个皇后不在同一行、同一列或者同一斜线上
算法的基本思想如下:
将第i个皇后摆放在第i行,i从1开始,每个皇后都从第1列开始尝试。尝试时判断在该列摆放皇后是否与前面的皇后有冲突,如果没有冲突,则在该列摆放皇后,并考虑摆放下一个皇后;如果有冲突,则考虑下一列。如果该行没有合适的位置,回溯到上一个皇后,考虑在原来位置的 个位置上继续尝试摆放皇后,……直到找到所有合理摆放方案。

下面是算法的Java语言实现。
(1)常量和变量说明
n:皇后数,棋盘规模为nxn
queen[]:皇后的摆放位置数组,queen[i]表示第i个皇后的位置,1<=queen[i]<=n

public class Backtracking {
    public static int n =4;    //皇后的数量
    public static int count = 0;  //统计n皇后问题的方案数
    public static int[] queen = new int[n + 1];
    public static void main(String[] args) {
        Nqueen(1);
        System.out.println(n+"皇后问题的解法总数:"+count);
            }
//     1、
    public static void Nqueen(int j){
        int i;
        for (i = 1; i <= n; i++) {
            queen[j] = i;
            if (place(j)){
                if (j == n){   //如果所有皇后都摆放好,则输出当前的北方方案
                    show();
                    count++;
                }else{     //否则继续摆放下一个皇后
                    Nqueen(j + 1);
                }
            }
        }
    }
//    2、检查当前列是否可以放置皇后,不能返回false,可以摆放返回true
    public static boolean place(int j){
        int i;
        for (i = 1;i < j;i++){  //检查与已摆放的皇后是否在同一列或者同意斜线上
            if (queen[i]==queen[j]||Math.abs(queen[i] - queen[j]) == (j - i)){
                return false;
            }
        }
        return true;
    }
//    3、输出所有皇后摆放的方案
    public static void show(){
        int i;
        System.out.print("(");
        for (i = 1; i <= n; i++) {
            System.out.print(queen[i]);
        }
        System.out.print(")\n");

    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值