算法&数据结构
基本概念
-
data structure
- 存储数据的方式
-
algorithm
- 解决方法
-
算法优劣
- 时间
- 空间
-
时间复杂度
- 随着规模的扩大时间的变化
-
空间复杂度
- 随着规模的扩大空间的变化
排序
冒泡排序
- 相邻的两个元素逆序,就需要交换
public static void main(String[] args){
int[] arr = {5,3,4,2,1,7,6,9,8};
sort(arr);
print(arr);
}
public static void sort(int[] arr){
for(int i=arr.length-1;i>0;i--){
for(int j=0;i<arr.length-1-i;j++){
if(arr[j]>arr[j+1]){
swap(arr,j,j+1);
}
}
}
}
public 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[] arr){
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+'" ");
}
}
优化
public static void main(String[] args){
int[] arr = {5,3,4,2,1,7,6,9,8};
boolean flag = false; //标识 是否进行过交换
for(int i=arr.length-1;i>0;i--){
for(int j=0;i<arr.length-1-i;j++){
if(arr[j]>arr[j+1]){
flag = true;
swap(arr,j,j+1);
}
}
if(!flag){
// 一次交换也没发生,已经排序完成
break;
}else{
flag = false; // 重置
}
}
print(arr);
}
public 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[] arr){
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+'" ");
}
}
选择排序
- 选择排序
- 简单
- 不稳定
public static void main(String[] args){
int[] arr = {5,3,4,2,1,7,6,9,8};
sort(arr);
print(arr);
}
public static void sort(int arr){
for(int i=0;i<arr.length-1;i++){
int minPos = i;
for(int j=i+1;j<arr.length;j++){
if(arr[j]<arr[minPos]){
minPos = j;
}
}
swap(arr,i,minPos);
}
}
public 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[] arr){
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+'" ");
}
}
插入排序
public static void main(String[] args){
int[] arr = {5,3,4,2,1,7,6,9,8};
sort(arr);
print(arr);
}
public static void sort(int[] arr){
for(int i=1;i<arr.length;i++){
for(int j=i;j>0;j--){
if(arr[j]<arr[j-1]){
swap(arr,j,j-1);
}
}
}
}
public 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[] arr){
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+'" ");
}
}
希尔排序
- 在局部排序时可以采用插入或者交换方法排序
public static void main(String[] args){
int[] arr = {5,3,4,2,1,7,6,9,8,0};
sort(arr);
print(arr);
}
public static void sort(int[] arr){
int h=1;
while(h<=arr.length/3){
h=h*3+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);
}
}
}
}
}
public 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[] arr){
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+'" ");
}
}
快速排序
- 单轴快排
- 双轴快排
public static void main(String[] args){
int[] arr = {5,3,4,2,1,7,6,9,8};
sort(arr,0,arr.length-1);
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);
}
public 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--;
if(left < right) swap(arr,left,right);
}
swap(arr,left,rightBound);
return left;
}
public 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[] arr){
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+'" ");
}
}
归并排序
public class QuickSort{
public static void main(String[] args){
int[] arr = {-9,78,0,23,-567,70};
quickSort(arr,0,arr.length-1);
}
public static void quickSort(int[] arr,int left,int right){
int l = left; // 左下标
int r = right; // 右下标
int pivot = arr[{left+right}/2]; //中轴
int temp = 0; // 临时变量,交换时使用
// while循环目的时让比pivot值小的放左边
while(l<r){
// 在左边一致找,找到大于等于pivot的值,才退出
while(arr[r]<pivot){
l+=1;
}
// 在右边一致找,找到小于等于pivot的值,才退出
while(arr[r]>pivot){
r-=1;
}
// 如果l>=r,说明左右两边值已经全部满足要求
if(l>=r){
break;
}
temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
// 简化完后发现arr[l]==pivot值
if(arr[l]==pivot){
r -= 1;
}
if(arr[r]==pivot){
l += 1;
}
}
if(l==r){
l += 1;
r -= 1;
}
if(left<r){
quickSort(arr,left,r);
}
if(right>1){
quickSort(arr,r,right);
}
}
}
归并排序
- 分治策略
public class MergetSort{
pulic static void main(String[] args){
int arr[] = {5,4,6,7,3,7,2};
int temp[] = new int[arr.length];
mergeSort(arr,0,arr.length-1,temp);
}
// 分+合
public static void mergeSort(int[] arr,int left,int right,int[] temp){
if(left < right){
int mid = (left + right) /2;// 中间索引
// 向左递归
mergeSort(arr,left,mid,temp);
// 向右递归
mergeSort(arr,mid+1,right,temp);
// 合并
merge(arr,left,mid,right,temp);
}
}
// 合并
// arr 排序原始数组
// left 左边有序序列初始索引
// mid 中间索引
// right 右边最后段索引
// temp 中转数组
public static void merge(int[] arr,int left,int mid,int right,int[] temp){
int i=left; // 左边有序序列初始索引
int j = mid + 1; // 右边有序序列初始索引
int t = 0; // 指向temp当前索引
// 先把左右两边数据按规则填充到temp中
while(i<=mid && j <= right){
if(arr[i]<=arr[j]){
temp[t] = arr[i];
t += 1;
i += 1;
}else{
temp[t] = arr[j];
t += 1;
j += 1;
}
}
// 把剩余的数据一边全部填充到temp中
while(i<=mid){
// 左边剩余
temp[t] = arr[i];
t += 1;
i += 1;
}
while(j<= right){
temp[t] = arr[j];
t += 1;
j += 1;
}
// 剩余的元素拷贝到arr
t = 0;
int tempLeft = left;
while(tempLeft <= right){
arr[tempLeft] = temp[t];
tempLeft += 1;
t += 1;
}
}
}
基数排序
- 桶排序
- 按个位分桶
- 按桶依次取出放回原数组中
- 按十位分桶
- 按桶依次取出放回原数组中
- 按百位分桶
- 按桶依次取出放回原数组中
- 。。。
public class RedixSort{
public static void main(String[] args){
int[] arr = {53,3,542,754,14,214};
radixSort(arr);
}
public static void radixSort(int[] arr){
// 获取最大位数
int max = arr[0];
for(int i=0;i<arr.length;i++){
if(arr[i]>max){
max = arr[i];
}
}
int maxLength = (max+"").length();
// 空间换时间
int[][] bucket = new int[10][arr.length];
// 记录各桶存放数据
int[] bucketElementCounts = new int[10];
for(int i=0,n=1;i<maxLength;i++,n*=10){
for(int j=0;j<arr.length;j++){
// 取出每个元素个/十/百位数
int digitOfElement = arr[j]/n%10;
// 放入对应桶
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
bucketElementCounts[digitOfElement]++ ;
}
// 按照这个桶顺序重新放入原数组
int index = 0;
for(int k=0; k<bucketElementCounts.length;k++){
// 如果桶中有数据,存入原数组中
if(bucketElementCounts[k]!=0){
// 第k个桶
for(int l=0;l<bucketElementCounts[k];k++){
arr[index] = bucket[k][l];
index++;
}
bucketElementCounts[k] = 0;
}
}
}
}
}
计数排序
- 计数数组
public static void main(String[] args){
int[] arr = {5,3,4,2,1,7,6,9,8,0,2,3,3,5,6,2,3,1,2,0,4,6,7,8,9,8};//0~9
int [] result = sort(arr);
System.out.println(Arrays.toString(result));
}
public static int[] sort(int[] arr){
int[] result = new int[arr.length];
int[] count = new int[10];
for(int i=0;i<arr.length;i++){
count[arr[i]]++;
}
System.out.println(Arrays.toString(count));
/*
for(int i=0,j=0;j<count.length;j++){
while(count[i]-->0) result[i+1] = i ;
}
*/
for(int i=1;i<count.lenght;i++){
count[i] = count[i]+count[i-1];
}
System.out.println(Arrays.toString(count));
for(int i=arr.leingth-1;i>=0;i--){
result[--count[arr[i]]] = arr[i];
}
return result;
}