数据结构与算法_正在更新中。。。

一、线型数据结构

00.复杂度

(1)时间复杂度

每访问一个元素,时间复杂度记为1。如果一个数组长度为n,如果我们用遍历的方式来进行操作,那么访问n次才能够确定,时间复杂度记为n;

常见的时间复杂度有:1,N,Log n,N2,N3

(2)空间复杂度

原始数据空间为n,我们新开辟的空间大小是n的多少倍。

01.数组

​ **特点:**数组对象直接指向数组首地址,物理空间上是连续的。数据呈线状排列。
​ **优点:**在查找的时候,效率高。
​ **缺点:**因为空间是连续的,所以当磁盘的控件碎片较多的时候,我们可能无法存入大数据。即使内存空间足够,也无法存储。

(1)遍历与求和

public class Array001 {

    //数组遍历
    public static void print(int[] arr) {
        if (arr == null || arr.length == 0) {
            System.out.println("数组为空,取消遍历");
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }

    //数组求和
    public static int sum(int[] arr) {
        int total = 0;
        if (arr == null) {
            return total;
        }
        for (int i = 0; i < arr.length; i++) {
            total += arr[i];
        }
        return total;
    }

    public static void main(String[] args) {
        int[] arr = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        System.out.println("数组遍历为:");
        print(arr);
        System.out.println();
        System.out.println("数组的和为:" + sum(arr));
    }
}

(2)数组排序

a.冒泡排序

特点是一遍比较,一边交换;

/**
 * 冒泡排序
 */
public class BubbleSort {

    public static void sort(int[] arr) {
        if (arr == null || arr.length == 0 || arr.length == 1) {
            return;
        }
        for (int i = 0; i < arr.length; 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;
                }
            }
        }
    }

    public static void main(String[] args) {
        int[] arr = new int[]{4, 3, 5, 7, 9, 8, 6, 1, 2};
        sort(arr);
        for (int i : arr) {
            System.out.println(i);
        }
    }
}
b.选择排序

特点是先遍历选择最大值的索引,再和未排序的最后一个元素进行交换;

/**
 * 选择排序
 */
public class SelectionSort {

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

    public static void main(String[] args) {
        int[] arr = new int[]{3, 2, 5, 6, 9, 1, 4, 7, 9, 8};
        sort(arr);
        for (int i : arr) {
            System.out.println(i);
        }
    }
}

(3)有序数组的合并

思路:新建一个足够长度的新数组,循环比较两个数组的较小值,谁小,谁就放到新数组中。

/**
 * 合并两个有序的数据
 */
public class OrderlyArrayMerge {

    public static int[] merge1(int[] arrA, int[] arrB) {
        if (arrA == null) {
            return arrB;
        }
        if (arrB == null) {
            return arrA;
        }
        int[] result = new int[arrA.length + arrB.length];
        int p1 = 0;     //第一个数组的索引
        int p2 = 0;     //第二个数组的索引
        int pr = 0;     //新数组的索引
        while (p1 < arrA.length && p2 < arrB.length) {      //当p1和p2都没有越界时
            if (arrA[p1] < arrB[p2]) {      //谁小,谁就放在新数组里
                result[pr++] = arrA[p1++];
            } else {
                result[pr++] = arrB[p2++];
            }
        }
        if (p1 >= arrA.length) {            //如果p1放完了
            while (p2 < arrB.length) {      //则把p2剩余的放到新数组里
                result[pr++] = arrB[p2++];
            }
        } else {
            while (p1 < arrA.length) {
                result[pr++] = arrA[p1++];
            }
        }
        return result;
    }

    public static int[] merge2(int[] arrA, int[] arrB) {
        if (arrA == null) {
            return arrB;
        }
        if (arrB == null) {
            return arrA;
        }
        int[] result = new int[arrA.length + arrB.length];
        int p1 = 0;
        int p2 = 0;
        int pr = 0;
        while (p1 < arrA.length || p2 < arrB.length) {          //当p1和p2有一个没放完时即循环
            //如果p2越界或p1比p2小,用p1的数据
            if (p2 >= arrB.length || arrA[p1] < arrB[p2]) {
                result[pr++] = arrA[p1++];
            } else {
                result[pr++] = arrB[p2++];
            }
        }
        return result;
    }

    public static void main(String[] args) {
        int[] a = new int[]{1, 3, 5, 7, 9, 11, 13, 15};
        int[] b = new int[]{2, 4, 5, 6, 8, 9, 10};
//        int[] c = merge1(a, b);
        int[] c = merge2(a, b);
        for (int i : c) {
            System.out.println(i);
        }
    }
}

02.链表

​ **特点:**空间可以不是连续的。需要在存放数据的同时,多创建一个空间用来存放数据。
​ **优点:**不受空间大小的影响,只要有空间,就能存储数据,不会受空间连续的制约。
​ **缺点:**查找效率没有数组高;需要多开辟一块空间。

(1)遍历与求和

  • 链表结点类Node

    public class Node {
        public int val;
        public Node next;
    
        public Node() {
        }
    
        public Node(int val) {
            this.val = val;
        }
    }
    
  • 代码演示

public class LinkTable001 {

    //遍历链表
    public static void print(Node node) {
        while (node != null) {
            System.out.print(node.val + " ");
            node = node.next;
        }
    }

    //递归遍历
    public static void print2(Node node) {
        //递归出口
        if (node == null) return;
        //递归操作
        System.out.print(node.val + " ");
        //下一次递归
        print2(node.next);
        //每次完成之后做的事情
        System.out.print(node.val + " ");
    }

    //链表求和
    public static int sum(Node node) {
        if (null == node) {
            return 0;
        }
        int total = 0;
        while (node != null) {
            total += node.val;
            node = node.next;
        }
        return total;
    }

    //链表递归求和
    public static int sum2(Node node,int total) {
        //递归出口
        if (node == null) return total;
        //递归操作
        total += node.val;
        //下一次递归
        return sum2(node.next, total);
    }

    public static void main(String[] args) {
        Node head = new Node(1);
        Node node1 = new Node(2);
        Node node2 = new Node(3);
        Node node3 = new Node(4);
        Node node4 = new Node(5);

        head.next = node1;
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        System.out.println("链表普通遍历:");
        print(head);
        System.out.println();
        System.out.println("链表递归遍历:");
        print2(head);
        System.out.println();
        System.out.println("链表求和:" + sum(head));
        System.out.println("链表递归求和:" + sum2(head, 0));
    }
}

(2)链表逆置

public class LinkTable002 {

    //链表逆置
    public static Node change(Node node) {      //a传进来
        if (node.next.next != null) {
            Node result = change(node.next);    //a,change b;
            node.next.next = node;
            node.next = null;
            return result;
        } else {        //如果是倒数第二个结点
            Node result = node.next;    //记录最后一个结点
            node.next.next = node;      //最后一个结点指向前一个结点
            node.next = null;           //前一个结点指向空
            return result;              //返回最后一个结点
        }
    }

    public static Node change2(Node node) {
        Node result = null;
        if (node.next.next != null) {
            result = change(node.next);
        } else {
            result = node.next;
        }
        //递归操作
        node.next.next = node;
        node.next = null;
        return result;
    }

    public static void main(String[] args) {
        Node a = new Node(1);
        Node b = new Node(2);
        Node c = new Node(3);
        Node d = new Node(4);
        Node e = new Node(5);

        a.next = b;
        b.next = c;
        c.next = d;
        d.next = e;
    }
}

03.栈

  • 自定义栈MyStack

    /**
     * 用数组封装栈
     */
    public class MyStack {
    
        private int top;
        private int[] data;
    
        public MyStack(int size) throws Exception {
            if (size <= 0) {
                throw new Exception("栈的长度必须大于0");
            }
            this.data = new int[size];
        }
    
        public void push(int value) throws Exception {
            if (top >= this.data.length) {
                throw new Exception("栈满了");
            }
            data[top++] = value;
        }
    
        public int pop() throws Exception {
            if (top <= 0) {
                throw new Exception("栈空了");
            }
            return data[--top];
        }
    
    }
    
  • 测试栈

    public class StackTest {
    
        public static void main(String[] args) throws Exception {
            MyStack myStack = new MyStack(3);
            myStack.push(1);
            myStack.push(2);
            myStack.push(3);
            System.out.println(myStack.pop());
            System.out.println(myStack.pop());
            System.out.println(myStack.pop());
        }
    }
    

04.队列

(1)用链表实现队列

/**
 * 用链表实现队列
 */
public class MyQueue {

    private Node head;      //队列的头
    private Node tail;      //队列的尾
    private int maxSize;    //队列的最大容量
    private int size;       //队列的当前存值个数

    public MyQueue(int maxSize) {
        this.maxSize = maxSize;
        this.size = 0;
    }

    public void push(int value) throws Exception {
        if (size >= maxSize) {
            throw new Exception("队列满啦");
        }
        Node node = new Node(value);
        if (size == 0) {
            head = node;
            tail = node;
        } else {
            tail.next = node;
            tail = node;
        }
        size++;
    }

    public int pop() throws Exception {
        if (size <= 0) {
            throw new Exception("队列空啦");
        }
        int result = head.val;
        head = head.next;
        size--;
        return result;
    }

}

(2)两个栈实现队列

public class MyQueueWithStack {

    private MyStack myStack1;
    private MyStack myStack2;

    public MyQueueWithStack(int size) throws Exception {
        myStack1 = new MyStack(size);
        myStack2 = new MyStack(size);
    }

    public void push(int value) throws Exception {
        myStack1.push(value);
    }

    public int pop() throws Exception {
        while (!myStack1.isEmpty()) {
            myStack2.push(myStack1.pop());
        }
        int result = myStack2.pop();
        while (!myStack2.isEmpty()) {
            myStack1.push(myStack2.pop());
        }
        return result;
    }
}
  • 测试队列

    public class QueueTest {
    
        public static void main(String[] args) throws Exception {
            MyQueue myQueue = new MyQueue(3);
            myQueue.push(1);
            myQueue.push(2);
            myQueue.push(3);
            System.out.println(myQueue.pop());
            System.out.println(myQueue.pop());
            System.out.println(myQueue.pop());
            MyQueueWithStack myQueueWithStack = new MyQueueWithStack(3);
            myQueueWithStack.push(1);
            myQueueWithStack.push(2);
            myQueueWithStack.push(3);
            System.out.println(myQueueWithStack.pop());
            System.out.println(myQueueWithStack.pop());
            System.out.println(myQueueWithStack.pop());
        }
    }
    

二、二维数据结构

01.二维数组

02.邻接链表

03.拓扑结构-图

04.树

06.链表的递归遍历

public class Test {

    public static void printNode(Node node) {
        if (node == null) {			//递归出口
            return;
        }
        System.out.println(node.getVal());		//对每个节点的通用操作
        printNode(node.getNext());				//向下递归点
        System.out.println(node.getVal());
    }

    public static void main(String[] args) {
        Node node1 = new Node(1);
        Node node2 = new Node(2);
        Node node3 = new Node(3);
        Node node4 = new Node(4);
        Node node5 = new Node(5);

        node1.setNext(node2);
        node2.setNext(node3);
        node3.setNext(node4);
        node4.setNext(node5);

        printNode(node1);   //1,2,3,4,5,5,4,3,2,1
    }
}

07.链表的逆置

    public static Node change(Node node) {
        if (node.next.next != null) {       //如果当前节点不是D
            Node result = change(node.next);    //将第二个节点传入递归执行
            node.next.next = node;
            node.next = null;
            return result;
        } else {            //如果当前节点是D节点
            Node result = node.next;        //得到E节点
            node.next.next = node;          //E节点指向D节点
            node.next = null;               //D节点指向null
            return result;                  //将E节点返回
        }
    }

    public static Node change2(Node node) {
        Node result = null;
        if (node.next.next != null) {
            result = change2(node.next);
        } else {
            result = node.next;
        }
        node.next.next = node;
        node.next = null;
        return result;
    }

08.栈和队列

public class Test {

    public static void main(String[] args) throws Exception {
//        MyStack myStack = new MyStack(3);     //测试栈
//        myStack.push(1);
//        myStack.push(2);
//        myStack.push(3);
//        System.out.println(myStack.pop());
//        System.out.println(myStack.pop());
//        System.out.println(myStack.pop());

        MyQueue myQueue = new MyQueue(3);
        myQueue.push(1);
        myQueue.push(2);
        myQueue.push(3);
        System.out.println(myQueue.pop());
        System.out.println(myQueue.pop());
        System.out.println(myQueue.pop());
        System.out.println(myQueue.pop());



    }
}

class MyQueue {
    Node head = null;
    Node tail = null;
    int maxSize;
    int size;

    public MyQueue(int maxSize) {
        this.maxSize = maxSize;
        this.size = 0;
    }

    public void push (int val) throws Exception {
        Node node = new Node(val);
        if (size >= maxSize) {
            throw new Exception("队列满了");
        }
        if (size == 0) {
            head = node;
            tail = node;
        } else {
            tail.next = node;
            tail = node;
        }
        size++;
    }

    public int pop() throws Exception {
        if (size <= 0) {
            throw new Exception("队列里没数据了");
        }
        size--;
        int result = head.val;
        head = head.next;
        return result;
    }

}

class MyStack {
    int[] data;
    int top = 0;
    public MyStack(int size) {
        this.data = new int[size];
    }

    public void push(int val) throws Exception {
        if (top >= this.data.length) {
            throw new Exception("栈满了");
        }
        this.data[top] = val;
        top++;
    }

    public int pop() throws Exception {
        if (top <= 0) {
            throw new Exception("栈里没数据了");
        }
        return this.data[--top];
    }
    public boolean isEmpty() {
        if (this.top == 0) {
            return true;
        } else {
            return false;
        }
    }
}

09.用两个栈模拟队列

class MyQueueWithStack {
    MyStack stack1;
    MyStack stack2;

    public MyQueueWithStack(int size) {
        stack1 = new MyStack(size);
        stack2 = new MyStack(size);
    }

    public void push(int val) throws Exception {
        stack1.push(val);
    }

    public int pop() throws Exception {
        while (!stack1.isEmpty()) {
            stack2.push(stack1.pop());
        }
        int result = stack2.pop();
        while (!stack2.isEmpty()) {
            stack1.push(stack2.pop());
        }
        return result;
    }
}

public class Test {

    public static void main(String[] args) throws Exception {
        MyQueueWithStack myQueueWithStack = new MyQueueWithStack(10);
        myQueueWithStack.push(1);
        myQueueWithStack.push(2);
        myQueueWithStack.push(3);
        System.out.println(myQueueWithStack.pop());
        System.out.println(myQueueWithStack.pop());
        System.out.println(myQueueWithStack.pop());
    }
}

10.时间复杂度

​ 假设我们有个数组,我们要查找数组中是否存在某个数。

​ 如何来衡量写的算法效率是否高?

​ 可以用时间吗?不可以

​ 每访问一个元素,时间复杂度记为1。如果一个数组长度为n,如果我们用遍历的方式来进行操作,那么访问n次才能够确定。时间复杂度记为n。

​ 1,N,Log n,N2,N3

11.空间复杂度

​ 用了多少额外的空间,我们暂且估计原始数据的大小为n,我们新开辟的空间是n的多少倍。

12.冒泡排序

//冒泡排序
public class Test {

    //排序的本质是什么?
    //排序是比较大小,非常错误的
    //排序是比较优先级,然后进行位置交换
    //在比较大小的时候,例如从小到大排列,数字越小,优先级越高

    public static boolean compare(int a, int b) {
        if (a > b) {
            return true;
        }
        return false;
    }

    public static void change(int[] arr, int aIndex, int bIndex) {
        int temp = arr[aIndex];
        arr[aIndex] = arr[bIndex];
        arr[bIndex] = temp;
    }

    public static void sort(int[] arr) {		//边比较边交换
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (compare(arr[j], arr[j + 1])) {
                    change(arr, j, j + 1);
                }
            }
        }
    }

    public static void main(String[] args) {
        int[] arr = new int[]{2, 4, 3, 1, 9, 0, 6, 7, 8, 5};
        sort(arr);
        for (int i : arr) {
            System.out.println(i);
        }
    }
}

13.选择排序

    public static void sort(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            int maxIndex = 0;
            for (int j = 1; j < arr.length - i; j++) {
                if (compare(arr[j], arr[maxIndex])) {
                    maxIndex = j;
                }
            }
            change(arr, maxIndex, arr.length - 1 - i);
        }
    }

14.有序数组的合并

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值