当前位置: 首页 > article >正文

数据结构——常见数据结构和应用

数据结构是计算机科学中的一个基本概念,它涉及数据的组织、管理和存储方式。以下是对数据结构的详细解释:

一、定义与组成

  1. 数据描述事物的符号记录,是计算机程序的输入和输出。它可以以多种形式存在,如数字、文字、图像、声音等。数据是信息的载体,具有可识别性、可存储性、可处理性和可传输性等特点。
  2. 数据对象必须由软件理解的复合信息表示。它可以是外部实体、事物、偶发事件或事件、角色、组织单位、地点或结构等的抽象表示。数据对象具有独立性、意义性和封装性等特点,只封装数据,没有对数据的操作。
  3. 数据元素数据的基本单位,也叫做结点或记录。在计算机程序中,数据元素通常作为一个整体进行考虑和处理。数据元素由数据项组成,数据项是构成数据元素的不可分割的最小单位。
  4. 数据结构相互之间存在一种或多种特定关系的数据元素的集合。这些关系定义了数据元素之间的逻辑结构和存储结构,以及可以对这些数据元素执行的操作。

二、逻辑结构

逻辑结构与数据的存储无关,独立于计算机,是从具体问题抽象出来的数学模型。常见的逻辑结构包括:

  1. 集合:数据结构中的元素之间除了“同属一个集合”的相互关系外,别无其他关系。
  2. 线性结构:数据结构中的元素存在一对一的相互关系。典型的线性表有链表、栈和队列。它们共同的特点就是数据之间的线性关系,除了头结点和尾结点之外,每个结点都有唯一的前驱和唯一的后继,也就是所谓的一对一的关系。
  3. 树形结构:数据结构中的元素存在一对多的相互关系。每个节点有0个或多个子节点,没有父节点的节点称为根节点,每一个非根节点有且只有一个父节点。除了根节点外,每个子节点可以分为多个不相交的子树。
  4. 图形结构:数据结构中的元素存在多对多的相互关系。

三、存储结构

存储结构依赖于计算机,是数据的物理视图。常见的存储结构有:

  1. 顺序存储:用一段物理地址连续的存储单元依次存储数据元素的线性结构。特点为空间连续,支持随机访问,但中间或前面部分的插入删除时间复杂度较高,且增容的代价比较大。
  2. 链式存储:一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。包括无头单向非循环链表、带头双向循环链表等。特点为插入和删除操作的时间复杂度为O(1),但需要额外的存储空间来保存指针;查找元素需要遍历整个链表,耗时较长。
  3. 索引存储:通过索引表来存储数据元素。索引表由若干索引项组成,每个索引项至少包含两个内容:关键字和该关键字所在数据的物理地址。
  4. 哈希存储:根据关键码值(key-value)直接访问的数据结构。特点为查找、插入和删除操作的时间复杂度通常为O(1),但需要额外的存储空间来保存哈希函数和哈希表。

四、运算

运算是定义在数据的逻辑结构上的一组操作,用于对数据元素进行处理以实现特定功能。每种数据结构都有一个运算的集合,如搜索、插入、删除、更新、排序等。

五、分类

数据结构可以根据其逻辑结构和存储结构的不同进行分类,例如:

  1. 线性数据结构:如数组、链表(单链表、双向链表、循环链表)、栈和队列()等。
  2. 非线性数据结构:如树(包括二叉树、平衡二叉树、红黑树等)、图(包括有向图和无向图)和堆(包括最大堆和最小堆)等。

六、常见数据结构及其应用

  1. 数组:用于存储和管理有序集合的数据,如列表。
    public class ArrayExample {
        public static void main(String[] args) {
            int[] array = {1, 2, 3, 4, 5};
            
            // 访问数组元素
            System.out.println(array[0]); // 输出 1
            
            // 修改数组元素
            array[0] = 10;
            System.out.println(array[0]); // 输出 10
        }
    }

  2. 链表:同样用于存储和管理有序集合的数据,如队列、栈等。链表允许在任意位置进行插入和删除操作,具有灵活性。
    class Node {
        int data;
        Node next;
        
        Node(int data) {
            this.data = data;
            this.next = null;
        }
    }
    
    public class LinkedListExample {
        Node head;
        
        public void add(int data) {
            Node newNode = new Node(data);
            if (head == null) {
                head = newNode;
            } else {
                Node temp = head;
                while (temp.next != null) {
                    temp = temp.next;
                }
                temp.next = newNode;
            }
        }
        
        public void printList() {
            Node temp = head;
            while (temp != null) {
                System.out.print(temp.data + " ");
                temp = temp.next;
            }
        }
        
        public static void main(String[] args) {
            LinkedListExample list = new LinkedListExample();
            list.add(1);
            list.add(2);
            list.add(3);
            list.printList(); // 输出 1 2 3
        }
    }

  3. :一种特殊的线性表,只允许在固定的一端进行插入和删除元素操作。特点为后进先出(LIFO),通常用于递归调用、函数调用栈等场景。
    public class StackExample {
        private int maxSize;
        private int[] stackArray;
        private int top;
        
        public StackExample(int size) {
            this.maxSize = size;
            this.stackArray = new int[maxSize];
            this.top = -1;
        }
        
        public void push(int value) {
            if (isFull()) {
                System.out.println("Stack is full");
                return;
            }
            stackArray[++top] = value;
        }
        
        public int pop() {
            if (isEmpty()) {
                throw new RuntimeException("Stack is empty");
            }
            return stackArray[top--];
        }
        
        public boolean isEmpty() {
            return (top == -1);
        }
        
        public boolean isFull() {
            return (top == maxSize - 1);
        }
        
        public static void main(String[] args) {
            StackExample stack = new StackExample(3);
            stack.push(1);
            stack.push(2);
            stack.push(3);
            System.out.println(stack.pop()); // 输出 3
            System.out.println(stack.pop()); // 输出 2
        }
    }

  4. 队列:一种先进先出的线性表,允许在一端进行插入操作(入队),在另一端进行删除操作(出队)。特点为先进先出(FIFO),常用于缓冲区、任务调度等场景。
    public class QueueExample {
        private int front, rear, size;
        private int capacity;
        private int[] queue;
        
        public QueueExample(int capacity) {
            this.capacity = capacity;
            this.front = this.size = 0;
            this.rear = capacity - 1;
            this.queue = new int[capacity];
        }
        
        private boolean isFull() {
            return size == capacity;
        }
        
        private boolean isEmpty() {
            return size == 0;
        }
        
        public void enqueue(int item) {
            if (isFull())
                return;
            rear = (rear + 1) % capacity;
            queue[rear] = item;
            size = size + 1;
        }
        
        public int dequeue() {
            int item = -1;
            if (isEmpty())
                return item;
            item = queue[front];
            front = (front + 1) % capacity;
            size = size - 1;
            return item;
        }
        
        public int front() {
            if (isEmpty())
                return -1;
            return queue[front];
        }
        
        public int rear() {
            if (isEmpty())
                return -1;
            return queue[rear];
        }
        
        public static void main(String[] args) {
            QueueExample queue = new QueueExample(5);
            
            queue.enqueue(10);
            queue.enqueue(20);
            queue.enqueue(30);
            queue.enqueue(40);
            
            System.out.println(queue.dequeue()); // 输出 10
            System.out.println(queue.front());   // 输出 20
            System.out.println(queue.rear());    // 输出 40
        }
    }

  5. :由n(n≥1)个有限节点组成的一个具有层次关系的集合。常用于表示层次结构,如文件系统、组织结构图等。
    class TreeNode {
        int data;
        TreeNode left, right;
        
        TreeNode(int item) {
            data = item;
            left = right = null;
        }
    }
    
    // 二叉树的基本操作(如插入、遍历等)需要额外实现

  6. :一系列顶点(元素)的集合,这些顶点通过一系列边连接起来组成图这种数据结构。顶点用圆圈表示,边就是这些圆圈之间的连线。图用于表示网络结构,如社交网络、交通网络等。
    import java.util.*;
    
    class Graph {
        private int V; // 顶点数
        private LinkedList<Integer> adj[]; // 邻接表
        
        // 构造函数
        Graph(int v) {
            V = v;
            adj = new LinkedList[v];
            for (int i = 0; i < v; ++i)
                adj[i] = new LinkedList();
        }
        
        // 添加边
        void addEdge(int v, int w) {
            adj[v].add(w); // 添加w到v的列表
        }
        
        // 打印图(用于调试)
        void printGraph() {
            for (int v = 0; v < V; ++v) {
                System.out.print("\n Adjacency list of vertex " + v);
                for (Integer n : adj[v])
                    System.out.print(" -> " + n);
                System.out.println();
            }
        }
        
        public static void main(String args[]) {
            Graph g1 = new Graph(5);
            
            g1.addEdge(0, 1);
            g1.addEdge(0, 4);
            g1.addEdge(1, 2);
            g1.addEdge(1, 3);
            g1.addEdge(1, 4);
            g1.addEdge(2, 3);
            g1.addEdge(3, 4);
            
            g1.printGraph();
        }
    }

  7. :一种特殊的完全二叉树结构,分为最大堆和最小堆。最大堆中每个节点的值都大于或等于其子节点的值;最小堆中每个节点的值都小于或等于其子节点的值。常用于实现优先队列等场景。
    import java.util.Arrays;
    
    public class MaxHeap {
        private int[] heap;
        private int size;
        private int capacity;
    
        // 构造函数,初始化堆
        public MaxHeap(int capacity) {
            this.capacity = capacity;
            this.heap = new int[capacity];
            this.size = 0;
        }
    
        // 堆化一个数组以构建最大堆
        public MaxHeap(int[] array) {
            this.capacity = array.length;
            this.heap = new int[capacity];
            this.size = capacity;
            System.arraycopy(array, 0, heap, 0, capacity);
            for (int i = size / 2 - 1; i >= 0; i--) {
                heapifyDown(i);
            }
        }
    
        // 插入一个新元素
        public void insert(int value) {
            if (size == capacity) {
                throw new IllegalStateException("Heap is full");
            }
            heap[size] = value;
            size++;
            heapifyUp(size - 1);
        }
    
        // 获取堆顶元素(最大值)
        public int getMax() {
            if (size == 0) {
                throw new IllegalStateException("Heap is empty");
            }
            return heap[0];
        }
    
        // 移除堆顶元素
        public int extractMax() {
            if (size == 0) {
                throw new IllegalStateException("Heap is empty");
            }
            int maxValue = heap[0];
            heap[0] = heap[size - 1];
            size--;
            heapifyDown(0);
            return maxValue;
        }
    
        // 上滤操作,用于插入新元素后维护堆的性质
        private void heapifyUp(int index) {
            while (index > 0) {
                int parentIndex = (index - 1) / 2;
                if (heap[parentIndex] < heap[index]) {
                    swap(parentIndex, index);
                    index = parentIndex;
                } else {
                    break;
                }
            }
        }
    
        // 下滤操作,用于移除堆顶元素后维护堆的性质
        private void heapifyDown(int index) {
            int largest = index;
            int leftChild = 2 * index + 1;
            int rightChild = 2 * index + 2;
    
            if (leftChild < size && heap[leftChild] > heap[largest]) {
                largest = leftChild;
            }
    
            if (rightChild < size && heap[rightChild] > heap[largest]) {
                largest = rightChild;
            }
    
            if (largest != index) {
                swap(index, largest);
                heapifyDown(largest);
            }
        }
    
        // 交换堆中两个元素的位置
        private void swap(int index1, int index2) {
            int temp = heap[index1];
            heap[index1] = heap[index2];
            heap[index2] = temp;
        }
    
        // 打印堆的内容
        public void printHeap() {
            System.out.println(Arrays.toString(Arrays.copyOfRange(heap, 0, size)));
        }
    
        // 主方法,用于测试
        public static void main(String[] args) {
            MaxHeap maxHeap = new MaxHeap(10);
            maxHeap.insert(3);
            maxHeap.insert(1);
            maxHeap.insert(6);
            maxHeap.insert(5);
            maxHeap.insert(2);
            maxHeap.insert(4);
    
            maxHeap.printHeap(); // 输出堆的内容
    
            System.out.println("Max: " + maxHeap.getMax()); // 输出最大值
            System.out.println("After extracting max:");
            maxHeap.extractMax();
            maxHeap.printHeap(); // 输出移除最大值后的堆内容
        }
    }

  8. 散列表:也叫哈希表,是根据键和值(key和value)直接进行访问的数据结构。通过key和value来映射到集合中的一个位置,从而可以很快找到集合中的对应元素。常用于实现快速查找、缓存等场景。
    import java.util.HashMap;
    import java.util.Map;
    
    public class HashTableExample {
        public static void main(String[] args) {
            // 创建一个HashMap实例
            Map<String, Integer> hashMap = new HashMap<>();
    
            // 插入键值对
            hashMap.put("apple", 1);
            hashMap.put("banana", 2);
            hashMap.put("orange", 3);
    
            // 访问元素
            System.out.println("Value for key 'apple': " + hashMap.get("apple"));
    
            // 检查键是否存在
            if (hashMap.containsKey("banana")) {
                System.out.println("Key 'banana' exists in the map.");
            }
    
            // 移除键值对
            hashMap.remove("orange");
    
            // 遍历HashMap
            for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
                System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
            }
        }
    }


http://www.kler.cn/a/445523.html

相关文章:

  • 网络安全概论——防火墙原理与设计
  • Unity 圆形循环复用滚动列表
  • javax.net.ssl.SSLPeerUnverifiedException: Hostname 192.168.13.13 not verified:
  • 如何通过HTTP API新建Collection
  • WebSocket入门与结合redis
  • 架构信息收集(小迪网络安全笔记~
  • 项目搭建+图片(添加+图片)
  • dolphinscheduler服务RPC框架源码解析(八)RPC提供者服务整合Spring框架实现
  • React-antd组件库 - 让Menu子菜单项水平排列 - 下拉菜单排序 - 自定义子菜单展示方式
  • 电商后台革命:RPA 自动化商品信息录入与更新【52rpa.com】
  • MongoDB常见面试题总结(上)
  • 用链表的详解和综合应用——实现链表的创建、输出、删除及添加结点(C语言)
  • VR线上展厅的色彩管理如何影响用户情绪?
  • 【踩坑】Pytorch与CUDA版本的关系及安装
  • 基于Spring Boot的房屋租赁管理系统
  • 在 Ubuntu 上安装 Muduo 网络库的详细指南
  • 巧记斜边函数hypot
  • JavaScript网络请求( XMLHttpRequest 对象,进度事件, 跨源资源共享)
  • express+mysql实现注册功能
  • NPM国内镜像源多选择与镜像快速切换工具(nrm)介绍
  • 慢牛提速经典K线形态-突破下跌起始位和回档三五线,以及徐徐上升三种形态
  • 软件工程
  • iPhone通话记录生成器,苹果一键生成通话记录,手机ios制造专家
  • 差分矩阵(Difference Matrix)与累计和矩阵(Running Sum Matrix)的概念与应用:中英双语
  • [NOIP2004 提高组] 合并果子-STL容器优先队列priority_queue
  • Apache Solr RCE(CVE-2019-0193)--vulhub