数据结构和算法——数据结构

news2024/11/20 18:47:07

数据结构:

线性结构:

顺序存储方式,顺序表

常见的顺序存储结构有:数组、队列、链表、栈

链式存储方式,链表

 队列:

队列可以使用数组结构或者链表结构来存储,先入先出,后进后出。

数组结构的队列:
public class Demo {
    public static void main(String[] args) {
        CircleArrayQueue arrayQueue = new CircleArrayQueue(3);
        char key;
        Scanner scanner = new Scanner(System.in);
        boolean loop = true;
        while (loop) {
            System.out.println("s(show):显示队列");
            System.out.println("e(exit):退出程序");
            System.out.println("a(add):添加数据到队列");
            System.out.println("g(get):从队列取出数据");
            System.out.println("h(head):查看队列头的数据");
            key = scanner.next().charAt(0);
            switch (key) {
                case 's':
                    arrayQueue.showQueue();
                    break;
                case 'a':
                    System.out.println("请输入一个数字");
                    int value = scanner.nextInt();
                    arrayQueue.addQueue(value);
                    break;
                case 'g':
                    try {
                        int res = arrayQueue.getQueue();
                        System.out.println("取出的数据为=" + res);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':
                    loop = false;
                    scanner.close();
                    System.out.println("程序退出...");
                    break;
                case 'h':
                    try {
                        int res = arrayQueue.headQueue();
                        System.out.println("查看的数据为=" + res);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                default:
                    break;
            }
        }
    }
}

class CircleArrayQueue {
    private int maxSize;
    // 指向队列头的位置
    private int front;
    // 指向队列尾的数据的下一个的位置,它指向的队尾的数据代表有值的
    private int rear;
    private int[] arr;

    public CircleArrayQueue(int arrMaxSize) {
        // 实际上队列有maxSize个元素,因为空出了一个位置
        maxSize = arrMaxSize + 1;
        arr = new int[maxSize];
        front = rear = 0;
    }

    public boolean isFull() {
        return (rear + 1) % maxSize == front;
    }

    public boolean isEmpty() {
        return front == rear;
    }

    public void addQueue(int n) {
        if (isFull()) {
            System.out.println("队列为满,不能加入数据");
            return;
        }
        arr[rear] = n;
        rear++;
        if (rear % maxSize == 0) {
            rear = 0;
        }
    }

    public int getQueue() {
        if (isEmpty()) {
            throw new RuntimeException("队列为空,不能取值");
        }
        int res = arr[front];
        front++;
        if (front % maxSize == 0) {
            front = 0;
        }
        return res;
    }

    public void showQueue() {
        if (isEmpty()) {
            System.out.println("队列为空,没有数据");
            return;
        }
//        for (int i = front; i != rear; i = (i + 1) % maxSize) {
        for (int i = front; i < front + size(); i++) {
            System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
        }
    }

    public int headQueue() {
        if (isEmpty()) {
            throw new RuntimeException("队列为空,没有头数据");
        }
        return arr[front];
    }

    private int size() {
        return (rear + maxSize - front) % maxSize;
    }
}
链表结构的队列:
public class SingleLinkListDemo {
    public static void main(String[] args) {
        HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
        HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");
        HeroNode hero3 = new HeroNode(3, "吴用", "智多星");
        SingleLinkList singleLinkList = new SingleLinkList();
        singleLinkList.add(hero3);
        singleLinkList.add(hero2);
        singleLinkList.add(hero1);
//        singleLinkList.add(hero3);
//        HeroNode newHero = new HeroNode(3, "张三", "法外狂徒");
//        singleLinkList.update(newHero);
        HeroNode delHero1 = new HeroNode(1, "", "");
        singleLinkList.del(delHero1);
        singleLinkList.reverse();
        singleLinkList.list();
    }
}

class SingleLinkList {
    private HeroNode headNode = new HeroNode(0, "", "");

    // 非递归反转
    public void reverse3() {
        if (headNode.getNext() == null || headNode.getNext().getNext() == null) {
            return;
        }
        HeroNode nextNode1, nextNode2, nextNode3;
        nextNode1 = headNode.getNext();
        nextNode2 = nextNode1.getNext();
        nextNode3 = nextNode2.getNext();
        nextNode2.setNext(nextNode1);
        nextNode1.setNext(null);

        while (nextNode3 != null) {
            nextNode1 = nextNode2;
            nextNode2 = nextNode3;
            nextNode3 = nextNode3.getNext();
            nextNode2.setNext(nextNode1);
        }
        headNode.setNext(nextNode2);
    }

    // 递归反转
    public void reverse() {
        HeroNode nextNode = headNode.getNext();
        headNode.setNext(reverse2(headNode.getNext()));
        nextNode.setNext(null);
    }
    private HeroNode reverse2(HeroNode heroNode) {
        if (heroNode.getNext() != null) {
            HeroNode lastNode = reverse2(heroNode.getNext());
            heroNode.getNext().setNext(heroNode);
            return lastNode;
        }
        return heroNode;
    }

    public void del(HeroNode delHeroNode) {
        if (headNode.getNext() == null) {
            System.out.println("链表为空");
            return;
        }
        HeroNode preNode, nextNode;
        preNode = headNode;
        nextNode = headNode.getNext();
        while (nextNode != null) {
            if (nextNode.getNo() == delHeroNode.getNo()) {
                preNode.setNext(nextNode.getNext());
                // nextNode.setNext(null);
                return;
            }
            preNode = nextNode;
            nextNode = nextNode.getNext();
        }
        System.out.println("删除编号= " + delHeroNode.getNo() + " 的元素没有找到");
    }

    public void update(HeroNode newHeroNode) {
        if (headNode.getNext() == null) {
            System.out.println("链表为空");
            return;
        }
        HeroNode preNode, nextNode;
        preNode = headNode;
        nextNode = headNode.getNext();
        while (nextNode != null) {
            if (nextNode.getNo() == newHeroNode.getNo()) {
                newHeroNode.setNext(nextNode.getNext());
                preNode.setNext(newHeroNode);
                return;
            }
            preNode = nextNode;
            nextNode = nextNode.getNext();
        }
        System.out.println("编号= " + newHeroNode.getNo() + " 的元素没有找到");
    }

    public void add(HeroNode heroNode) {
        HeroNode nextNode, preNode;
        preNode = headNode;
        nextNode = headNode.getNext();
        // 头插法
        if (nextNode == null) {
            headNode.setNext(heroNode);
            heroNode.setNext(null);
            return;
        }
        // 中插法
        while (nextNode != null) {
            if (heroNode.getNo() < nextNode.getNo()) {
                preNode.setNext(heroNode);
                heroNode.setNext(nextNode);
                return;
            }
            // 相同的数据不能进行插入
            if (heroNode.getNo() == nextNode.getNo()) {
                System.out.println("编号=" + heroNode.getNo() + " 已存在,不能添加");
                return;
            }
            preNode = nextNode;
            nextNode = nextNode.getNext();
        }
        // 尾插法
        preNode.setNext(heroNode);
        heroNode.setNext(null);
    }

    public void list() {
        HeroNode tmpNode = headNode.getNext();
        if (tmpNode == null) {
            System.out.println("链表为空");
            return;
        }
        while (tmpNode != null) {
            System.out.println("node= " + tmpNode + " -->");
            tmpNode = tmpNode.getNext();
        }
    }
}

@Data
class HeroNode {
    private int no;
    private String name;
    private String nickName;
    private HeroNode next;

    public HeroNode(int hNo, String hName, String hNickName) {
        this.no = hNo;
        this.name = hName;
        this.nickName = hNickName;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickName='" + nickName + '\'' +
                '}';
    }
}
链表的面试题:
单向链表应用场景:
约瑟夫环问题:

代码:

package org.example.josephu;

public class Josephu {
    public static void main(String[] args) {
        CircleSingleLinkedList list = new CircleSingleLinkedList();
        list.addBoy(5);
        list.countBoy(1, 2, 5);
//        list.showBoy();
    }
}

class CircleSingleLinkedList {
    private Boy first = null;

    public void addBoy(int nums) {
        if (nums < 2) {
            System.out.println("nums的值不正确");
            return;
        }
        Boy curBoy = null;
        for (int i = 0; i < nums; i++) {
            Boy boy = new Boy(i + 1);
            if (i == 0) {
                first = boy;
                first.setNext(first);
                curBoy = first;
            } else {
                curBoy.setNext(boy);
                boy.setNext(first);
                curBoy = boy;
            }
        }
    }

    public void showBoy() {
        if (first == null) {
            System.out.println("链表为空");
            return;
        }
        Boy curBoy = first;
        do {
            System.out.println("编号= " + curBoy.getNo() + " -->");
            curBoy = curBoy.getNext();
        } while (curBoy != first);
    }

    /**
     * @param startNo  从第几个开始
     * @param countNum 数几下
     * @param nums     最初有多少个小孩
     */
    public void countBoy(int startNo, int countNum, int nums) {
        if (first == null || startNo < 1 || startNo > nums) {
            System.out.println("参数输入有误,请重新输入");
            return;
        }
        Boy helper = first;
        while (helper.getNext() != first) {
            helper = helper.getNext();
        }
        for (int i = 0; i < startNo - 1; i++) {
            first = first.getNext();
            helper = helper.getNext();
        }
        while (helper != first) {
            for (int i = 0; i < countNum - 1; i++) {
                first = first.getNext();
                helper = helper.getNext();
            }
            System.out.println("小孩 " + first.getNo() + " 出圈");
            first = first.getNext();
            helper.setNext(first);
//            nums--;
        }
        System.out.println("最后留在圈中的小孩编号 " + first.getNo());
    }
}

class Boy {
    private int no;
    private Boy next;

    public Boy(int no) {
        this.no = no;
    }

    //#region get|set
    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public Boy getNext() {
        return next;
    }

    public void setNext(Boy next) {
        this.next = next;
    }
    //#endregion
}
栈结构:

代码:

package org.example.stack;

import java.sql.SQLOutput;
import java.util.Scanner;

public class ArrayStackDemo {
    public static void main(String[] args) {
        ArrayStack stack = new ArrayStack(4);
        String key;
        boolean loop = true;
        Scanner scanner = new Scanner(System.in);
        while (loop) {
            System.out.println("show:表示显示栈");
            System.out.println("exit:表示退出栈");
            System.out.println("push:表示压栈");
            System.out.println("pop:表示出栈");
            System.out.println("请输入你的选择:");
            key = scanner.next();
            switch (key) {
                case "s":
                    stack.list();
                    break;
                case "e":
                    loop = false;
                    break;
                case "pu":
                    try {
                        System.out.println("请输入要压栈的数据");
                        int value = scanner.nextInt();
                        stack.push(value);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case "po":
                    try {
                        System.out.println(stack.pop());
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                default:
                    System.out.println("输入有误");
                    break;
            }
        }
        System.out.println("程序退出了...");
    }
}

class ArrayStack {
    private int maxSize;
    private int[] stack;
    private int top = -1;

    public ArrayStack(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[maxSize];
    }

    public boolean isFull() {
        return top == maxSize - 1;
    }

    public boolean isEmpty() {
        return top == -1;
    }

    public void push(int value) {
        if (isFull()) {
            System.out.println("栈满");
            return;
        }
        top++;
        stack[top] = value;
    }

    public int pop() {
        if (isEmpty()) {
            throw new RuntimeException("栈空,没有数据");
        }
        int res = stack[top];
        top--;
        return res;
    }

    public void list() {
        if (isEmpty()) {
            System.out.println("栈空,没有数据");
            return;
        }
        for (int i = top; i >= 0; i--) {
            System.out.printf("a[%d]=%d\n", i, stack[i]);
        }
    }
}
用栈实现一个简单的计算器:

中缀表达式:人阅读的表达式。

package org.example.stack;

public class Calculator {
    public static void main(String[] args) {
        String expression = "7*2*2-5+1-5+3-4";
        ArrayStack2 numStack = new ArrayStack2(10);
        ArrayStack2 operStack = new ArrayStack2(10);
        int index = 0;
        int num1 = 0;
        int num2 = 0;
        int oper = 0;
        int res = 0;
        char ch = ' ';
        while (true) {
            ch = expression.substring(index, index + 1).charAt(0);
            if (operStack.isOper(ch)) {
                if (!operStack.isEmpty()) {
                    if (operStack.priority(ch) <= operStack.priority(operStack.peek())) {
                        num1 = numStack.pop();
                        num2 = numStack.pop();
                        oper = operStack.pop();
                        res = numStack.cal(num1, num2, (char) oper);
                        numStack.push(res);
                        operStack.push(ch);
                    } else {
                        operStack.push(ch);
                    }
                } else {
                    operStack.push(ch);
                }
            } else {
                // numStack.push(ch - '0');
                int keepNum = ch - '0';
                while (index < expression.length() - 1) {
                    index++;
                    ch = expression.substring(index, index + 1).charAt(0);
                    if (!operStack.isOper(ch)) {
                        keepNum = keepNum * 10 + (ch - '0');
                    } else {
                        index--;
                        break;
                    }
                }
                numStack.push(keepNum);
            }
            index++;
            if (index == expression.length()) {
                break;
            }
        }
        while (true) {
            if (operStack.isEmpty()) {
                break;
            }
            num1 = numStack.pop();
            num2 = numStack.pop();
            oper = operStack.pop();
            res = numStack.cal(num1, num2, (char) oper);
            numStack.push(res);
        }
        System.out.printf("表达式 %s = %d\n", expression, numStack.pop());
    }
}

class ArrayStack2 {
    private int maxSize;
    private int[] stack;
    private int top = -1;

    public ArrayStack2(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[maxSize];
    }

    public boolean isFull() {
        return top == maxSize - 1;
    }

    public boolean isEmpty() {
        return top == -1;
    }

    public void push(int value) {
        if (isFull()) {
            System.out.println("栈满");
            return;
        }
        top++;
        stack[top] = value;
    }

    public int pop() {
        if (isEmpty()) {
            throw new RuntimeException("栈空,没有数据");
        }
        int res = stack[top];
        top--;
        return res;
    }

    public void list() {
        if (isEmpty()) {
            System.out.println("栈空,没有数据");
            return;
        }
        for (int i = top; i >= 0; i--) {
            System.out.printf("a[%d]=%d\n", i, stack[i]);
        }
    }

    public int priority(int oper) {
        if (oper == '*' || oper == '/') {
            return 1;
        } else if (oper == '+' || oper == '-') {
            return 0;
        }
        return -1;
    }

    public boolean isOper(char val) {
        return val == '+' || val == '-' || val == '*' || val == '/';
    }

    public int cal(int num1, int num2, char oper) {
        int res = 0;
        switch (oper) {
            case '+':
                res = num1 + num2;
                break;
            case '-':
                res = num2 - num1;
                break;
            case '*':
                res = num1 * num2;
                break;
            case '/':
                res = num2 / num1;
                break;
            default:
                break;
        }
        return res;
    }

    public int peek() {
        return stack[top];
    }
}
非线性结构:

常见的非线性结构有:二维数组、多维数组、广义表、树结构、图结构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1062075.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OK3568 forlinx系统编译过程及问题汇总

1. 共享文件夹无法加载&#xff1b;通过网上把文件夹加载后&#xff0c;拷贝文件很慢&#xff0c;任务管理器查看发现硬盘读写速率很低。解决办法&#xff1a;重新安装vmware tools。 2. 拷贝Linux源码到虚拟机&#xff0c;解压。 3. 虚拟机基本库安装 forlinxubuntu:~$ sudo…

【图像分割】距离正则化水平集演化及其在图像分割中的应用(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

并网逆变器+VSG控制+预同步控制+电流电流双环控制(Simulink仿真实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

微服务技术栈-初识Docker

文章目录 前言一、Docker概念二、安装Docker三、Docker服务命令四、Docker镜像和容器Docker镜像相关命令Docker容器相关命令 总结 前言 docker技术风靡全球&#xff0c;它的功能就是将linux容器中的应用代码打包,可以轻松的在服务器之间进行迁移。docker运行程序的过程就是去仓…

办公环境中最常用的邮箱是什么?

随着互联网的普及&#xff0c;电子邮件已经成为了人们日常生活和工作中不可或缺的一部分。为了更好地了解办公邮箱的使用情况&#xff0c;我们对不同群体的办公邮箱使用进行了一次调查。本文将为您详细介绍最常用的办公邮箱及其特点。 一、调查背景 本次调查旨在了解中国各行各…

堆--数据流中第K大元素

如果对于堆不是太认识&#xff0c;请点击&#xff1a;堆的初步认识-CSDN博客 数据流与上述堆--数组中第K大元素-CSDN博客的数组区别&#xff1a; 数据流的数据是动态变化的&#xff0c;数组是写死的 堆--数组中第K大元素-CSDN博客题的小顶堆加一个方法&#xff1a; class MinH…

C语言编程经典100例——1至10例

目录 第 1 例 第 2 例 第 3 例 第 4 例 第 5 例 第 6 例 第 7 例 第 8 例 第 9 例 第 10 例 第 1 例 程序源码&#xff1a; /* 题目&#xff1a;有 1、2、3、4 四个数字&#xff0c;能组成多少个互不相同且无重复数字的三位数&#xff1f;分别都是多少&#xff1f;…

CCF CSP认证 历年题目自练 Day22

CCF CSP认证 历年题目自练 Day22 题目一 试题编号&#xff1a; 201912-1 试题名称&#xff1a; 报数 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 512.0MB 题目分析&#xff08;个人理解&#xff09; 每一个人都要报多少个数字&#xff0c;我选择字典存储&#xff0…

Folium 笔记:MarkerCluster

在一张地图上以聚簇的形式显示大量的标记&#xff08;markers&#xff09; 举例&#xff1a; import folium from folium.plugins import MarkerCluster import randomm folium.Map(location[45.5236, -122.6750], zoom_start13) # 创建一个基本的地图marker_cluster Marker…

VAE(变分自动编码器)

1.自编码器存在的局限性 自编码器的隐空间的规则性是一个难点&#xff0c;其取决于初始空间中数据的分布、隐空间的大小和编码器的结构。我们很难先验地确保编码器与生成过程兼容并智能地组织隐空间&#xff0c;因此可能导致隐空间的某些点将在解码时给出无意义的内容。注意&am…

剑指offer——JZ76 删除链表中重复的结点 解题思路与具体代码【C++】

一、题目描述与要求 删除链表中重复的结点_牛客题霸_牛客网 (nowcoder.com) 题目描述 在一个排序的链表中&#xff0c;存在重复的结点&#xff0c;请删除该链表中重复的结点&#xff0c;重复的结点不保留&#xff0c;返回链表头指针。 例如&#xff0c;链表 1->2->3-&…

1802_在Linux系统上开发ARM单机片机嵌入式软件

全部学习汇总&#xff1a; GreyZhang/little_bits_of_linux: My notes on the trip of learning linux. (github.com) 1. 在Linux上也有嵌入式的开发环境&#xff0c;或许还有很多。不过&#xff0c;我现在接触到的大部分还是Windows居多。这一份文件介绍的是一个mbed platform…

springcloudAlibaba之Nacos服务注册源码分析

Nacos服务注册源码分析 Nacos服务注册原理Nacos服务注册怎么做的Nacos服务注册源码解读 带着以上三个问题&#xff0c;进入到今天的源码解读 问题1:Nacos服务注册原理 Nacos首先从bootstrap.yml配置文件中读取我们配置好的nacos配置&#xff0c;这里面一般包括spring.applic…

亚马逊,速卖通,国际站卖家如何找到真实干净的买家账号测评补单

对于卖家而言&#xff0c;测评资源确实是一项宝贵的财富。通过自养号和广告相结合的策略&#xff0c;可以快速有效地提升产品销量、增加转化率以及提高Listing的权重。这是一个很好的方法来优化产品在平台上的表现 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&…

小谈设计模式(18)—适配器模式

小谈设计模式&#xff08;18&#xff09;—适配器模式 专栏介绍专栏地址专栏介绍 适配器模式角色分析目标接口&#xff08;Target&#xff09;源接口&#xff08;Adaptee&#xff09;适配器&#xff08;Adapter&#xff09; 核心思想应用场景Java程序实现输出结果程序分析123 优…

【Python】基于OpenCV人脸追踪、手势识别控制的求生之路FPS游戏操作

【Python】基于OpenCV人脸追踪、手势识别控制的求生之路FPS游戏操作 文章目录 手势识别人脸追踪键盘控制整体代码附录&#xff1a;列表的赋值类型和py打包列表赋值BUG复现代码改进优化总结 py打包 视频&#xff1a; 基于OpenCV人脸追踪、手势识别控制的求实之路FPS游戏操作 手…

两文学会scala (下)|保姆级别教程(超详细)

上文内容概括&#xff1a; Scala 概述与安装、变量、运算符、流程控制、函数式编程、面向对象 上文链接&#xff1a;两文学会scala &#xff08;上&#xff09;&#xff5c;保姆级别教程&#xff08;超详细&#xff09;_超爱慢的博客-CSDN博客 目录 第7章 集合 7.1 集合简介…

增强负样本提高CPI表现

确定CPI对药物发现至关重要。由于实验验证CPI通常是耗时和昂贵的&#xff0c;计算方法有望促进这一过程。可用CPI数据库的快速增长加速了许多用于CPI预测的机器学习方法发展。然而&#xff0c;它们的性能&#xff0c;特别是它们对外部数据的泛化性&#xff0c;经常受到数据不平…

根据您的数据量定制的ChatGPT,改变客户服务的方式

在当今竞争激烈的商业环境中&#xff0c;提供优质的客户服务对于保持忠诚的客户群和推动业务增长至关重要。客户满意度已成为各行各企业的首要任务&#xff0c;因为它直接影响客户留存和品牌声誉。随着技术的进步&#xff0c;公司不断探索创新解决方案&#xff0c;以增强客户服…

Mac 挂载 Alist网盘

挂载服务器的Alist 网盘到 Mac mac,使用的是 CloundMounter 这个软件进行挂载 http://ip:port/dav/ 需要在末尾加上 /dav/ 在一些服务器上&#xff0c;为了提供WebDAV服务&#xff0c;需要在URL地址的末尾添加"/dav/“。这是因为WebDAV协议规定了一些标准的URL路径&#x…