算法与数据结构第一弹

Algorithm

Chap01

prerequisite

  1. generate random array
public static Integer[] gra(int n, int min, int max) {
    
    Integer[] arr = new Integer[n];
    for(int i = 0; i<n; i++) {
        arr[i] = new Integer((int)(Math.random() * (max - min + 1) + min));
        return arr;
    }
}   

The bounds are inclusive, ie[min,max].And be precautionary that min must be less than max.

Chap02

selection sort

int n = arr.length;
for(int i = 0; i < n; i++) {
    // 寻找[i, n)区间里的最小值的索引
    int minIndex = i;
    for(int j = i + 1; j < n; j++) 
        if(arr[j] < arr[i])
            minIndex = j;
    swap(arr, i, minIndex);
}

improvement in efficiency

int left = 0; right = arr.length - 1;
while(left < right) {
    int minIndex = left;
    int maxIndex = right;
    
    if(arr[minIndex].compareTo(arr[maxIndex]) > 0)
        swap(arr, minIndex, maxIndex);
    
    for(int i = left + 1; i < right; i++) {
        if(arr[i].comareTo(arr[minIndex]) < 0)
            minIndex = i;
        else if(arr[i].compareTo(arr[maxIndex]) > 0)
            maxIndex = i;
    
    swap(arr, left, minIndex);
    swap(arr, right, maxIndex);
    
    left++;
    right--;
    }
}
  • 在每一轮中, 可以同时找到当前未处理元素的最大值和最小值。

insertion sort

for(int i = 1; i < n; i++) {
    // 寻找arr[i]合适的插入位置
    for(int j = i; j > 0; j--) {
        // 某种程度上是循环继续的条件
        if(arr[j] < arr[j-1])
            swap(arr, j, j-1);
        else
            break;
    }
}

improvement in concision

for(int i = 1; i < n; i++) {
    // 寻找arr[i]合适的插入位置
    for(int j = i; j > 0 && arr[j] < arr[j-1]; j--) {
            swap(arr, j, j-1);
    }
}
  • 插入排序可以提前终止,而选择排序必须遍历所有元素。
  • 测试算法性能时注意使用相同的数组,运行时间的计算。

improvement in efficiency

for(int i = 1; i < n; i++) {
    Comparable e = arr[i];
    int j = i;
    for( ; j > 0 && arr[j-1].compareTo(e) > 0; j--) 
            arr[j] = arr[j-1];
    arr[j] = e;
}
  • 交换操作开销较大,改换成赋值和移动。即寻找arr[i]正确的位置,寻找的过程中元素后移,找到了将arr[i]赋值即可。
  • 插入排序对近乎有序的数组排序效果较好,对完全有序的数组排序的时间复杂度是O(n)级别的。

bubble sort

实现

优化

shell sort

  • 以h递减序列的话,time complexity可以达到O(n^1.5),是和插入排序一脉相承的。

继承
泛型
反射
包装

Chap03

merge sort

//V1.0
// 将arr[l...mid]和arr[mid+1...r]两部分进行归并
void merge(Comparable[] arr, int l, int mid, int r) {
    Comparable[] aux = Arrays.copyOfRange(arr, l, r+1);
    int i = l, j = mid + 1;
    for(int k = l; k < r; k++) {
        if(l > mid) {
            arr[k] = aux[j-l]; j++;
        } 
        else if(j > r) {
            arr[k] = aux[i-l]; i++;
        }
        else if((aux[i-l].compareTo(aux[j-l]) < 0) {
            arr[k] = aux[i-l]; i++;
        }
        else {
            arr[k] = aux[j-l]; j++;
        }
}
void sort(Comparable[] arr, int l, int r) {
    if(l >= r) return;
    int mid = (l+r)/2;
    sort(arr, l, mid);
    sort(arr, mid+1, r);
    merge(arr, l, mid, r);
}
  • 优化1:限定归并条件if(arr[mid] > arr[mid+1])
  • 优化2:防止递归到底,在数据较少时数据有序可能性更大,插入排序更有优势。
//V1.1
void insert(Comparable[] arr, int l, int r) {
    for(int i = l+1; i < r + 1; i++) {
        Comparable e = arr[i];
        int j = i;
        for(; j > 0 && arr[j-1].compareTo(e) > 0; j--) {
            arr[j] = arr[j-1];
        }
        arr[j] = e;
}
void merge(Comparable[] arr, int l, int mid, int r) {
    Comparable[] aux = Arrays.copyOfRange(arr, l, r+1);
    int i = l, j = mid + 1;
    for(int k = l; k < r; k++) {
        if(l > mid) {
            arr[k] = aux[j-l]; j++;
        } 
        else if(j > r) {
            arr[k] = aux[i-l]; i++;
        }
        else if((aux[i-l].compareTo(aux[j-l]) < 0) {
            arr[k] = aux[i-l]; i++;
        }
        else {
            arr[k] = aux[j-l]; j++;
        }
}
void sort(Comparable[] arr, int l, int r) {

    if(r - l <= 15) {
        insert(arr, l, r);
        return
    }
    
    int mid = (l+r)/2;
    sort(arr, l, mid);
    sort(arr, mid+1, r);
    
    if( arr[mid].compareTo(arr[mid+1]) > 0 )
        merge(arr, l, mid, r);
}

前面我们实现了自顶向下的归并排序,其中运用到了递归的思想,下面我们将从另一种角度自底向上重新进行实现,而这没有用到递归而是用到了迭代的思想。更重要的是,在这种方法中没有用到数组,它可以对更广泛的如链表等结构进行排序。

//V2.0
void mergeSortBU(Comparable[] arr, int n) {
    for(int size = 1; i < n; size += size) 
        for(int i = 0; i < n; i += size + size) 
            merge(arr, i, i+size-1, min(i+size+siize-1, n-1));
}
  • 补充思考:
    • 求mid时l+r越界怎么办
    • 数据较少时使用插入排序少怎么定义
    • 自底向上的优化
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 数据结构 Java中的数组有差不多一样的语法。只是java中处理8种基本类型,数组也是作为对象处理的,所以创建对...
    赵宇_阿特奇阅读 802评论 0 0
  • 数据结构与算法--归并排序 归并排序 归并排序基于一种称为“归并”的简单操作。比如考试可能会分年级排名和班级排名,...
    sunhaiyu阅读 980评论 0 6
  • 总结一下常见的排序算法。 排序分内排序和外排序。内排序:指在排序期间数据对象全部存放在内存的排序。外排序:指在排序...
    jiangliang阅读 1,486评论 0 1
  • 一. 写在前面 要学习算法,“排序”是一个回避不了的重要话题,在分析完并查集算法和常用数据结构之后,今天我们终于可...
    Leesper阅读 2,626评论 0 40
  • 在这个知识爆炸、信息泛滥的时代,每个人都应该培养自己的认知和学习的能力,以保证自己不被信息浪潮冲垮。那么怎样培养认...
    朱敏虎阅读 1,236评论 0 0

友情链接更多精彩内容