概述
什么是数据结构?
数据结构就是把数据元素按照一定的关系组织起来的集合,用来组织和存储数据
数据结构的分类:
逻辑结构:
- 集合结构
- 线性结构
- 树形结构
- 图形结构
物理结构:
- 顺序结构
- 链式结构
什么是算法?
根据一定的条件,对一些数据进行计算,得到需要的结果
优秀算法的目标
- 1.花最少的时间完成需求
- 2.占用最少的内存空间完成需求
算法分析
算法的时间复杂度分析
事后分析估算方法:如写计算时间的代码
事后分析估算方法:
因素:
- 算法采用的策略和方案
- 编译产生的代码质量
- 问题的输入规模(所谓的问题输入规模就是输入量的多少)
- 机器执行指令的速度
最重要的是把核心操作的次数和输入规模关联起来
- 算法函数中的常数可以忽略不计
- 算法函数中最高次幂的常数因子可以忽略
- 算法函数中最高次幂越小,算法效率越高
算法时间复杂度
大O记法
- 用常数1取代运行时间中的所有加法常数
- 在修改后的运算次数中,只保留高阶项
- 如果最高阶项存在,且常数因子不为1,则去除这个项相乘的常数
如:
- 算法一:3次:
O(1)
- 算法二:n+3:
O(n)
- 算法三:n^2+2次:
O(n^2)
常见的大O阶
- 线性阶(如循环)
- 平方阶(如嵌套循环)
- 立方阶(如三层嵌套循环)
- 常数阶
- 对数阶
O(1)<O(logn)<O(n)<O(nlogn)<O(n^2)
算法的空间复杂度分析(略)
以占用内存为标准,这里省略
排序
冒泡排序
public static void sort01(int[] arr){
for (int i=0;i<arr.length-1;i++){
for (int j=0;j<arr.length-i-1;j++){
if (arr[j]>arr[j+1]){
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
print(arr);
}
时间复杂度:O(n^2)
选择排序
public static void sort02(int[] arr){
for (int i=0;i<arr.length-1;i++){
int min=i;
for (int j=i+1;j<arr.length;j++){
if (arr[min]>arr[j]){
min=j;
}
}
if (min!=i){
int temp=arr[i];
arr[i]=arr[min];
arr[min]=temp;
}
}
print(arr);
}
时间复杂度:O(n^2)
插入排序
public static void sort03(int[] arr){
for (int i=1;i<arr.length;i++){
for (int j=i;j>0;j--){
if (arr[j-1]>arr[j]){
int temp=arr[j];
arr[j]=arr[j-1];
arr[j-1]=temp;
}else {
break;
}
}
}
print(arr);
}
时间复杂度:O(n^2)
希尔排序
public static void sort04(int[] arr){
int h=1;
while (h<arr.length/2){
h=h*2+1;
}
while(h>=1){
for(int i=h;i<arr.length;i++){
for (int j=i;j>=h;j-=h){
if (arr[j-h]>arr[j]){
int temp=arr[j];
arr[j]=arr[j-h];
arr[j-h]=temp;
}else {
break;
}
}
}
h=h/2;
}
print(arr);
}
归并排序
public class test {
public static void sort(int[] arr){
int l=0;
int r=arr.length-1;
mergeSort(arr,l,r);
for (int i=0;i<arr.length;i++){
System.out.print(arr[i]+"\t");
}
}
private static void mergeSort(int[] arr,int l,int r){
if (l>=r){
return;
}
int mid=(l+r)>>>1;
mergeSort(arr,l,mid);
mergeSort(arr,mid+1,r);
merge(arr,l,mid,r);
}
private static void merge(int[] arr,int l,int mid,int r){
int s1=l;
int s2=mid+1;
int[] tempArr=new int[r-l+1];
int i=0;
while (s1<=mid&&s2<=r){
if (arr[s1]<=arr[s2]){
tempArr[i++]=arr[s1++];
}else {
tempArr[i++]=arr[s2++];
}
}
while (s1<=mid){
tempArr[i++]=arr[s1++];
}
while (s2<=r){
tempArr[i++]=arr[s2++];
}
for (int j=0;j<tempArr.length;j++){
arr[l+j]=tempArr[j];
}
}
}
时间复杂度:O(nlogn)
快速排序
public class Quick02 {
public static void sort(int[] arr){
int left=0;
int right=arr.length-1;
partitionSort(arr,left,right);
for (int i=0;i<arr.length;i++){
System.out.print(arr[i]+"\t");
}
}
private static void partitionSort(int[] arr,int left,int right){
if (right<=left){
return;
}
int partition=partition(arr,left,right);
partitionSort(arr,left,partition-1);
partitionSort(arr,partition+1,right);
}
private static int partition(int[] arr,int left,int right){
int s1=left;
int s2=right+1;
while (true){
while (arr[left]<arr[--s2]){
if (s2<=left){
break;
}
}
while (arr[left]>arr[++s1]){
if (s1>=right){
break;
}
}
if (s1>=s2){
break;
}else {
int temp=arr[s1];
arr[s1]=arr[s2];
arr[s2]=temp;
}
}
int temp=arr[s2];
arr[s2]=arr[left];
arr[left]=temp;
return s2;
}
}
时间复杂度:
最优:O(nlogn)
最差:O(n^2)
平均:O(nlogn)
排序的稳定性:
数组arr中由若干个元素,其中A元素和B元素相等且在它前面,如果使用了某种排序算法后,A元素仍然在B元素前面,则说该算法是稳定的
常见算法的稳定性:
- 冒泡排序 :稳定的
- 选择排序 :不稳定的
- 插入排序 :稳定的
- 希尔排序 :不稳定的
- 归并排序 :稳定的
- 快速排序 :不稳定的