数据结构与算法入门

什么是数据结构

数据的存储与组织方式

数据结构的分类

逻辑结构与物理结构
逻辑结构分为线性结构与非线性结构。线性结构包括 :顺序表、栈、队列;非线性表包括:树、图
物理结构分为顺序存储结构与链式存储结构。线性存储结构:数组;链式存储结构:链表

什么是算法

指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制

评价算法的好坏

时间复杂度 + 空间复杂度 + 应用场景(重要因素)

时间复杂度

关键代码的执行次数

推导出时间复杂度,有如下几个原则:

  • 如果运行时间是常数数量级,则用常数1表示。
  • 只保留时间函数中的最高阶项
  • 如果最高阶项存在,则省去最高阶项前面的系数

O(n)

数据结构与算法入门_第1张图片

O(logn)

数据结构与算法入门_第2张图片

O(1)

数据结构与算法入门_第3张图片

O (n²)

数据结构与算法入门_第4张图片

空间复杂度

在运行过程中临时占用存储空间大小的量度。一般只考虑时间复杂度

应用场景

为什么要考虑应用场景

public class SwapData {
  
 public static void main(String[] args)
 {
    swap1();
    swap2();
    swap3();
 }
 
 /**
 * 方法一:借用第三方变量实现数据交换,可读性最好
 */
 public static void   swap1(){
    int a = 5;
    int b = 6;
    int temp = a;// temp = 5
    a = b;//a = 6
    b = temp;//b =5
    System.out.println("a = "+a);
    System.out.println("b = "+b);
 }

 /**
 * 方法二:不借用第三方变量实现数据交换
 */
 public static void   swap2(){
    int a = 5;
    int b = 6;
    a = a + b;//a=11
    b = a - b;//b=5
    a = a - b;//a =6
    System.out.println("a = "+a);
    System.out.println("b = "+b);
 }
 
  /**
 * 方法三:性能最优,位运算,一般用在嵌入式设备中
 */
 public static void   swap3(){
    int a = 5;
    int b = 6;
    a = a^b;
    b = a^b;
    a = a^b;
    System.out.println("a = "+a);
    System.out.println("b = "+b);
 }
}

虽然另外两种性能更好,但是 可读性差,所以在实际应用中,算法的应用场景也是十分重要的

线性表

顺序存储结构(数组)

数组是有限个相同类型的变量组成的有序集合。在内存中是顺序存储的。常用的操作是CRUD,即增删改查。

public class Array {
    private int[] mArray;
    private int mCapacity;
    private int mArraySize;//实际大小

    public Array(int capacity){
        if (capacity <= 0) {
            this.mCapacity = 1;
        }
        this.mCapacity = capacity;
        mArray = new int[mCapacity];
        this.mArraySize = 0;
    }

    /**
     * 增(时间复杂度O(n))
     * @param index
     * @param value
     * @return
     */
    public int add(int index,int value){
        if (index < 0 || index > this.mArraySize) {
            throw new IndexOutOfBoundsException();
        }
        if (this.mArraySize >= this.mArray.length) {//扩容
            resize();
        }
        for (int x = this.mArraySize - 1 ; x >= index;x--){
            mArray[x + 1] = mArray[x];// 后移
        }
        mArray[index] = value;
        mArraySize++;
        return index;
    }

    private void resize() {
        int[] newArray = new int[this.mCapacity * 2];
        System.arraycopy(this.mArray,0,newArray,0,this.mArray.length);
        this.mArray = newArray;
    }

    /**
     * 删(时间复杂度O(n))
     * @param index
     * @return
     * @throws IndexOutOfBoundsException
     */
    public int delete(int index) throws IndexOutOfBoundsException {
        if (index < 0 || index > this.mArraySize) {
            throw new IndexOutOfBoundsException();
        }
        int deleteValue = mArray[index];
        for (int x = index;x < this.mArraySize - 1;x++){
            mArray[x] = mArray[x+1];// 往前
            System.out.println("x = "+x);
        }
        mArraySize--;
        return deleteValue;
    }

    /**
     * 改(时间复杂度O(1))
     * @param index
     * @param value
     * @return
     * @throws IndexOutOfBoundsException
     */
    public int update(int index,int value) throws IndexOutOfBoundsException{
        if (index < 0 || index > this.mArraySize) {
            throw new IndexOutOfBoundsException();
        }
        this.mArray[index] = value;
        return index;
    }

    /**
     * 查(时间复杂度O(1))
     * @param index
     * @return
     * @throws IndexOutOfBoundsException
     */
    public int read(int index) throws IndexOutOfBoundsException{
        if (index < 0 || index > this.mArraySize) {
            throw new IndexOutOfBoundsException();
        }
        return this.mArray[index];
    }

    public void printArray(){
        for (int i = 0;i < this.mArraySize;i++){
            System.out.print(mArray[i]+" , ");
        }
        System.out.println();
    }
}

链式存储结构

链表是一种在物理上非连续的,非顺序的数据结构。由若干节点组成。分为单向链表和双向链表

单向链表

数据结构与算法入门_第5张图片
public class LinkedListDemo {
    class Node{
        public int data;
        public Node next;
        public Node(int data){
            this.data = data;
        }
    }

    private Node head;
    private Node last;
    private int listSize;// 链表大小

    public int add(int index,int data) throws Exception {
        if (index < 0 || index > this.listSize){
            throw new IndexOutOfBoundsException();
        }
        Node node = new Node(data);
        if (listSize == 0){// 如果链表为空
            head = node;
            last = node;
        } else if (index == 0) {// 1. 头部插入
            node.next = head;
            head = node;
        } else if (index == this.listSize ) {// 2. 插入尾部
            last.next = node;
            last = node;
        } else {// 3.中间插入
            Node prvNode = get(index - 1);
            node.next = prvNode.next;
            prvNode.next = node;
        }
        this.listSize++;
        return index;
    }

    public int delete(int index) throws Exception {
        if (index < 0 || index > this.listSize){
            throw new IndexOutOfBoundsException();
        }
        if (this.listSize == 0) {
            System.out.println("链表为空");
            return -1;
        }
        Node deleteNode = get(index);
        if (index == 0) {// 1. 头部
            head = head.next;
        } else if (index == this.listSize) {// 2. 尾部
            Node prvNode = get(index - 1);
            last = prvNode;
        } else {// 3. 中间
            Node prvNode = get(index - 1);
            prvNode.next = deleteNode.next;
        }
        deleteNode = null;
        this.listSize--;
        return index;
    }

    public int update(int index,int data) throws Exception {
        if (index < 0 || index > this.listSize){
            throw new IndexOutOfBoundsException();
        }
        Node node = get(index);
        node.data = data;
        return index;
    }

    public Node get(int index) throws Exception {
        if (index < 0 || index > this.listSize){
            throw new IndexOutOfBoundsException();
        }
        Node node = head;
        for (int i = 0;i < index;i++){
            node = node.next;
        }
        return node;
    }

    public void printLinkedList(){
        System.out.println("----------------------------------------");
        Node node = head;
        for (int i = 0;i < listSize;i++){
            System.out.print(node.data+" , ");
            node = node.next;
        }
        System.out.println();
        System.out.println("----------------------------------------");
    }
}

双向链表

双链表比单链表,查询效率更高,因为可以从后往前查找

public class LinkedListDemo {
    class Node{
        public int data;
        public Node next;
        public Node prv;
        public Node(int data){
            this.data = data;
        }
    }

    private Node head;
    private Node last;
    private int listSize;// 链表大小

    public int add(int index,int data) throws Exception {
        if (index < 0 || index > this.listSize){
            throw new IndexOutOfBoundsException();
        }
        Node node = new Node(data);
        if (listSize == 0){// 如果链表为空
            head = node;
            last = node;
        } else if (index == 0) {// 1. 头部插入
            node.next = head;
            head.prv = node;
            head = node;
        } else if (index == this.listSize ) {// 2. 插入尾部
            last.next = node;
            node.prv = last;
            last = node;
        } else {// 3.中间插入
            Node prvNode = get(index - 1);

            node.next = prvNode.next;
            prvNode.next.prv = node;

            prvNode.next = node;
            node.prv = prvNode;
        }
        this.listSize++;
        return index;
    }

    public int delete(int index) throws Exception {
        if (index < 0 || index > this.listSize){
            throw new IndexOutOfBoundsException();
        }
        if (this.listSize == 0) {
            System.out.println("链表为空");
            return -1;
        }
        Node deleteNode = get(index);
        if (index == 0) {// 1. 头部
            head = head.next;
        } else if (index == this.listSize) {// 2. 尾部
            Node prvNode = get(index - 1);
            last = prvNode;
        } else {// 3. 中间
            Node prvNode = get(index - 1);
            prvNode.next = deleteNode.next;
            deleteNode.next.prv = prvNode;
        }
        deleteNode = null;
        this.listSize--;
        return index;
    }

    public int update(int index,int data) throws Exception {
        if (index < 0 || index > this.listSize){
            throw new IndexOutOfBoundsException();
        }
        Node node = get(index);
        node.data = data;
        return index;
    }

    public Node get(int index) throws Exception {
        if (index < 0 || index > this.listSize){
            throw new IndexOutOfBoundsException();
        }
        Node node = head;
        for (int i = 0;i < index;i++){
            node = node.next;
        }
        return node;
    }

    public void printLinkedList(){
        System.out.println("----------------------------------------");
        Node node = head;
        for (int i = 0;i < listSize;i++){
            System.out.print(node.data+" , ");
            node = node.next;
        }
        System.out.println();
        System.out.println("----------------------------------------");
    }

    public void printLinkedListReverse(){
        System.out.println("----------------------------------------");
        Node node = last;
        for (int i = listSize;i > 0;i--){
            System.out.print(node.data+" , ");
            node = node.prv;
        }
        System.out.println();
        System.out.println("----------------------------------------");
    }
}

蛮力法

蛮力法(brute force method,也称为穷举法或者枚举法)
是一种简单直接地解决问题的方法,
常常直接基于问题的描述,
所以,蛮力法也是最容易应用的方法,
但是,用蛮力法设计的算法时间特性往往也是最低的,
典型的指数时间算法一般都是通过蛮力搜索而得到的。

冒泡排序

蛮力法的一种,当 N < 5时,比其他的算法要快。
斗牛棋牌中的排序,就是用的冒泡排序算法。

public class BubbleSort {
    public void bubbleSort(int[] arrays){
        for (int i = 1;i < arrays.length;i++){
            boolean flag = false;//标志位,用于减少算法的执行次数,时间复杂度可降至N
            for (int j = 0;j < arrays.length - i;j++){// 一趟
                if (arrays[j] > arrays[j+1]) {
                    // 交换数据
                    int temp = arrays[j];
                    arrays[j] = arrays[j+1];
                    arrays[j+1] = temp;
                    flag = true;
                }
            }
            if (flag == false) {
                break;
            }

            System.out.println("一趟 "+arrays[i]);
        }
    }

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

选择排序

public class SelectSort {
    public void selectSort(int[] arrays){
        for (int i = 0;i < arrays.length - 1;i++){
            int index = i;
            for (int j = i + 1;j < arrays.length;j++){// 一趟
                if (arrays[index] < arrays[j]) {
                    index = j;
                }
            }
            // 交换数据
            if (index != i) {
                int temp = arrays[i];
                arrays[i] = arrays[index];
                arrays[index] = temp;
                System.out.println("一趟 "+arrays[i]+" index = "+index);
            }
        }
    }

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

基数排序

基数排序,适合数据量在二三十个的情况

/**
 * Created by 48608 on 2017/12/6.
 */

public class Mahjong {
    public int suit;//筒,万,索
    public int rank;//点数 一  二  三

    public Mahjong(int suit, int rank) {
        this.suit = suit;
        this.rank = rank;
    }

    @Override
    public String toString() {
        return "("+this.suit+" "+this.rank+")";
    }
}

import java.util.LinkedList;

public class RadixSortUtils {
    public void radixSort(LinkedList mahjongs){
        LinkedList[] rankList = new LinkedList[9];
        // 第一步,按点数就行分类
        for (int i = 0;i < rankList.length;i++){
            rankList[i] = new LinkedList();
        }
        while(mahjongs.size() > 0){// 用for循环不行,因为大小在不断地变小
            Mahjong mahjong = mahjongs.remove();// 一个个的取出来
            rankList[mahjong.rank - 1].add(mahjong);
        }
        // 九个链表合成一个链表
        for (int i = 0;i < rankList.length;i++){
            mahjongs.addAll(rankList[i]);
        }



        // 第二步,按花色进行分类
        LinkedList[] suitList = new LinkedList[3];

        for (int i = 0;i < suitList.length;i++){
            suitList[i] = new LinkedList();
        }
        while (mahjongs.size() > 0){// 用for循环不行
            Mahjong mahjong = mahjongs.remove();// 一个个的取出来
            suitList[mahjong.suit - 1].add(mahjong);
        }

        // 三个链表合成一个链表
        for (int i = 0;i < suitList.length;i++){
            mahjongs.addAll(suitList[i]);
        }
    }
}

你可能感兴趣的:(数据结构与算法入门)