Java SE基础知识详解第[11]期—集合(Collection、数据结构、List、泛型深入)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: Java SE基础知识详解第[11]期—集合(Collection、数据结构、List、泛型深入)

集合(Collection、数据结构、List、泛型深入)

1.集合的概述

集合和数组都是容器。

数组的特点

数组定义完成并启动后,类型确定、长度固定

适合元素的个数和类型确定的业务场景,不适合做需要增删数据操作

集合的特点

集合的大小不固定,启动后可以动态变化,类型也可以选择不固定

集合非常适合做个数不确定的元素增删操作。

注意集合中只能存储引用类型数据如果要存储基本类型数据可以选用包装类

集合中存储的是元素的什么信息?

集合中存储的是元素对象的地址信息,如果想要查看内容信息,需要重写元素对象的toString方法

 

2.Collection集合的体系特点

集合类体系结构如下图所示。

AggregateSystem.png

①Collection单列集合,每个元素(数据)只包含一个值

②Map双列集合,每个元素包含两个值(键值对)

Collection集合体系结构如下图所示。

CollectionSystem.png

Collection集合特点

List系列集合:添加的元素是有序、可重复、有索引。

ArrayList、LinekdList:有序、可重复、有索引。

Set系列集合:添加的元素是无序、不重复、无索引。

HashSet: 无序、不重复、无索引。

LinkedHashSet:有序、不重复、无索引。

TreeSet:按照大小默认升序排序、不重复、无索引。

示例代码如下:

publicstaticvoidmain(String[] args) {
// list:有序 可重复 有索引Collectionlist=newArrayList();
list.add("Java");
list.add("MyBatis");
list.add("张三");
list.add("张三");
list.add("李四");
System.out.println(list); // [Java, MyBatis, 张三, 张三, 李四]// set:无序 不可重复 无索引Collectionlist2=newHashSet();
list2.add("Java");
list2.add("MyBatis");
list2.add("张三");
list.add("张三");
list.add("李四");
System.out.println(list2); // [Java, 张三, MyBatis]    }

集合对于泛型的支持

集合都是支持泛型的,可以在编译阶段约束集合只能操作某种数据类型

注意:集合和泛型都只能支持引用数据类型,不支持基本数据类型,所以集合中存储的元素都认为是对象。

3.Collection集合的常用API

Collection集合

Collection是单列集合的祖宗接口,它的功能是全部单列集合都可以继承使用的。

Collection API

方法名

说明

public boolean add(E e)

把给定的对象添加到当前集合中

public void clear()

清空集合中所有的元素

public boolean remove(E e)

把给定的对象在当前集合中删除

public boolean contains(Object obj)

判断当前集合中是否包含给定的对象

public boolean isEmpty()

判断当前集合是否为空

public int size()

返回集合中元素的个数

public Object[] toArray()

把集合中的元素,存储到数组中

boolean addAll(Collection<? extends E> c);

把参数集合中的元素拷贝到当前集合中,

且被拷贝的集合中元素不变

 

示例代码如下:

publicstaticvoidmain(String[] args) {
Collection<String>list=newArrayList<>();
// 1.    public boolean add(E e)    把给定的对象添加到当前集合中list.add("Java");
list.add("张三");
list.add("李四");
System.out.println(list); // [Java, 张三, 李四]// 2.    public void clear()    清空集合中所有的元素//        list.clear();//        System.out.println(list); // []// 3.   public boolean remove(E e)  把给定的对象在当前集合中删除list.add("Java");
list.remove("Java");
System.out.println(list); // [张三, 李四, Java] 默认删除集合中的第一个对应元素// 4.   public boolean contains(Object obj) 判断当前集合中是否包含给定的对象System.out.println(list.contains("Java")); // trueSystem.out.println(list.contains("MyBatis")); // false// 5.   public boolean isEmpty()    判断当前集合是否为空System.out.println(list.isEmpty()); // false// 6.   public int size()   返回集合中元素的个数System.out.println(list.size()); // 3// 7.   public Object[] toArray()   把集合中的元素,存储到数组中Object[] arr=list.toArray();
System.out.println("数组:"+Arrays.toString(arr)); // 数组:[张三, 李四, Java]System.out.println("------扩展------");
Collection<String>l1=newArrayList<>();
l1.add("Java");
l1.add("HTML");
System.out.println(l1); // [Java, HTML]Collection<String>l2=newArrayList<>();
l2.add("张三");
l2.add("李四");
System.out.println(l2); // [张三, 李四]l1.addAll(l2); // 把l2中的元素全部拷贝到l1中去,l2中元素不变System.out.println(l1); // [Java, HTML, 张三, 李四]System.out.println(l2); // [张三, 李四]    }

4.Collection集合的遍历方式

4.1方式一:迭代器

迭代器遍历概述

遍历就是一个一个的把容器中的元素访问一遍。

迭代器在Java中的代表是Iterator,迭代器是集合的专用遍历方式

Collection集合获取迭代器

方法名

说明

Iterator<E> iterator()

返回集合中的迭代器对象,该迭代器对象默认指向当前集合的0索引

 

Iterator中的常用方法

方法名

说明

boolean hasNext()

询问当前位置是否有元素存在,存在返回true ,不存在返回false

E next()

获取当前位置的元素,并同时将迭代器对象移向下一个位置

注意防止取出越界

 

示例代码如下:

publicstaticvoidmain(String[] args) {
Collection<String>list=newArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
System.out.println(list); // [张三, 李四, 王五]// 得到当前集合的迭代器对象Iterator<String>it=list.iterator();
Stringele=it.next(); // 默认指向0索引,每访问一次,指向位置+1//        System.out.println(ele); // 张三//        System.out.println(it.next()); // 李四//        System.out.println(it.next()); // 王五//        System.out.println(it.next()); // 报错NoSuchElementException,此时索引在第3位,访问越界,没有此元素异常while (it.hasNext()) { // 采用while循环,循环条件是询问当前位置有元素存在,使用hasNext()方法,存在返回true ,不存在返回falseSystem.out.print(it.next() +"\t"); // 张三   李四  王五        }
    }

4.2方式二:foreach/增强for循环

增强for循环遍历概述

既可以遍历集合也可以遍历数组。

其内部原理是一个Iterator迭代器,遍历集合相当于是迭代器的简化写法。

实现Iterator接口的类才可以使用迭代器和增强for,collection接口已经实现了Iterator接口。

增强for循环的格式如下图所示。

forPlus.png

示例代码如下:

publicstaticvoidmain(String[] args) {
Collection<String>list=newArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
System.out.println(list); // [张三, 李四, 王五]// foreach遍历集合for (Stringele : list) { // 自动提取集合/数组中的每一个元素System.out.print(ele+"\t"); // 张三 李四  王五        }
System.out.println();
// foreach遍历数组double[] scores= {80, 99.3, 67, 5, 77.8};
for (doublescore : scores) {
System.out.print(score+"\t"); // 80.0 99.3    67.0    5.0 77.8        }
    }

注:修改foreach循环中的变量的值对原集合/数组的值没有任何影响。

4.3方式三:lambda表达式

lambda表达式遍历集合概述

得益于JDK 8开始的新技术Lambda表达式,提供了一种更简单、更直接的遍历集合的方式。

Collection结合Lambda遍历的API

方法名

说明

default void forEach(Consumer<? super T> action):

结合lambda遍历集合

 

示例代码如下:

publicstaticvoidmain(String[] args) {
Collection<String>list=newArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
System.out.println(list); // [张三, 李四, 王五]//        list.forEach(new Consumer<String>() {//            @Override//            public void accept(String s) {//                System.out.print(s + "\t"); // 张三 李四  王五//            }//        });list.forEach(s->System.out.print(s+"\t")); // 张三    李四  王五    }

5.常见数据结构

5.1数据结构概述、栈、队列

数据结构概述

数据结构是计算机底层存储、组织数据的方式。是指数据相互之间是以什么方式排列在一起的。

通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。

常见的数据结构:栈、队列、数组、链表、二叉树、二叉查找树、平衡二叉树、红黑树、…

栈数据结构的执行特点:后进先出,先进后出

数据进入栈模型的过程称为:压/进栈

数据离开栈模型的过程称为:弹/出栈

栈数据结构的执行特点示意如下图所示。

Stack.png

队列数据结构的执行特点:先进先出,后进后出

数据从后端进入队列模型的过程称为:入队列

数据从前端离开队列模型的过程称为:出队列

队列数据结构的执行特点示意如下图所示。

Queue.png

5.2数组

数组是一种查询快,增删慢的模型

查询速度快:查询数据通过地址值和索引定位,查询任意数据耗时相同。(元素在内存中是连续存储的)

删除效率低:要将原始数据删除,同时后面每个数据前移

添加效率极低:添加位置后的每个数据后移,再添加元素,同时需要保证索引没有出现大于等于数组长度越位。

5.3链表

链表的特点:链表中的元素是在内存中不连续存储的,每个元素节点包含数据值和下一个元素的地址

链表查询相对慢(对比数组),无论查询哪个数据都要从头开始找

链表增删相对快(对比数组)。

链表的特点如下图所示。

LinkedList.png

如下图所示,链表种类分为单链表与双链表双链表支持从前往后搜索,也支持从后往前搜索

LinkedListSort.png

5.4二叉树、二叉查找树

二叉树的特点

只能有一个根节点,每个节点最多支持2个直接子节点。

节点的度:节点拥有的子树的个数,二叉树的度不大于叶子节点度为0的节点,也称之为终端结点。

高度:叶子结点的高度为1,叶子结点的父节点高度为2,以此类推,根节点的高度最高。

层:根节点在第一层,以此类推

兄弟节点:拥有共同父节点的节点互称为兄弟节点。

二叉查找树又称二叉排序树或者二叉搜索树,其结构如下图所示。

BinaryTree.png

特点:

每一个节点上最多有两个子节点。

左子树上所有节点的值都小于根节点的值。

右子树上所有节点的值都大于根节点的值。

目的:提高检索数据的性能。

5.5平衡二叉树

平衡二叉树是在满足查找二叉树的大小规则下,让树尽可能矮小,以此提高查数据的性能。

平衡二叉树的要求

任意节点的左右两个子树的高度差不超过1,任意节点的左右两个子树都是一颗平衡二叉树。

平衡二叉树在添加元素后可能导致不平衡,基本策略是进行左旋,或者右旋保证平衡。

5.6红黑树

红黑树概述

每一个节点可以是红或者黑,红黑树不是通过高度平衡的,它的平衡是通过“红黑规则”进行实现的。

红黑规则

每一个节点或是红色的,或者是黑色的,根节点必须是黑色

如果一个节点没有子节点或父节点,则该节点相应的指针属性为Nil,这些Nil视为叶节点,叶节点是黑色的。

如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连的情况)

对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。

6.List系列集合

6.1List集合特点、特有API

List系列集合特点

ArrayList、LinekdList:有序,可重复,有索引

有序:存储和取出的元素顺序一致

有索引:可以通过索引操作元素

可重复:存储的元素可以重复

List集合特有方法

List集合因为支持索引,所以多了很多索引操作的独特API,其他Collection的功能List也都继承了。

List集合特有方法

方法名

说明

void add(int index,E element)

在此集合中的指定位置插入指定的元素

E remove(int index)

删除指定索引处的元素,返回被删除的元素

E set(int index,E element)

修改指定索引处的元素,返回被修改的元素

E get(int index)

返回指定索引处的元素

 

示例代码如下:

publicstaticvoidmain(String[] args) {
List<String>list=newArrayList<>();
list.add("Java");
list.add("MySQL");
list.add("HTML");
System.out.println(list); // [Java, MySQL, HTML]//        void add(int index,E element) 在此集合中的指定位置插入指定的元素list.add(1, "MyBatis"); // [Java, MyBatis, MySQL, HTML]System.out.println(list);
//        E remove(int index)   删除指定索引处的元素,返回被删除的元素StringremoveEle=list.remove(2);
System.out.println(removeEle); // MySQLSystem.out.println(list); // [Java, MyBatis, HTML]//        E set(int index,E element)    修改指定索引处的元素,返回被修改的元素StringsetEle=list.set(1, "Python");
System.out.println(setEle); // MyBatisSystem.out.println(list); // [Java, Python, HTML]//        E get(int index)  返回指定索引处的元素StringgetEle=list.get(0);
System.out.println(getEle); // Java    }

List集合的遍历方式小结

①迭代器②增强for循环③Lambda表达式④for循环(因为List集合存在索引)

ArrayList集合的底层原理

ArrayList底层是基于数组实现的:根据索引定位元素快,增删需要做元素的移位操作。

第一次创建集合并添加第一个元素的时候,在底层创建一个默认长度为10的数组。

6.2LinkedList集合特点、特有API

LinkedList的特点

底层数据结构是双链表,查询慢,首尾操作的速度是极快的,所以多了很多首尾操作的特有API。

LinkedList集合特有方法

方法名

说明

public void addFirst (E e)

在该列表开头插入指定的元素

public void push(E e)

同public void addFirst (E e)(push更专业)

public void addLast (E e)

将指定的元素追加到此列表的末尾

public E getFirst ()

返回此列表中的第一个元素

public E getLast ()

返回此列表中的最后一个元素

public E removeFirst ()

从此列表中删除并返回第一个元素

public E pop()

同public E removeFirst ()(pop更专业)

public E removeLast ()

从此列表中删除并返回最后一个元素

 

示例代码如下:

publicstaticvoidmain(String[] args) {
// LinkedList可以完成队列结构、栈结构(双链表)// 栈LinkedList<String>stack=newLinkedList<>();
// 压栈/入栈//        stack.addFirst("第1颗子弹");stack.push("第1颗子弹");
stack.push("第2颗子弹");
stack.push("第3颗子弹");
stack.push("第4颗子弹");
System.out.println(stack); // [第4颗子弹, 第3颗子弹, 第2颗子弹, 第1颗子弹]// 弹栈/出栈//        System.out.println(stack.removeFirst()); // 第4颗子弹System.out.println(stack.pop()); // 第4颗子弹System.out.println(stack.pop()); // 第3颗子弹System.out.println(stack.pop()); // 第2颗子弹System.out.println(stack.pop()); // 第1颗子弹// 队列LinkedList<String>queue=newLinkedList<>();
// 入队queue.addLast("1号");
queue.addLast("2号");
queue.addLast("3号");
queue.addLast("4号");
System.out.println(queue); // [1号, 2号, 3号, 4号]// 出队System.out.println(queue.removeFirst()); // 1号System.out.println(queue.removeFirst()); // 2号System.out.println(queue.removeFirst()); // 3号System.out.println(queue.removeFirst()); // 4号    }

7.补充知识:集合的并发修改异常问题

问题引出

当我们从集合中找出某个元素并删除的时候可能出现一种并发修改异常问题。

哪些遍历存在问题?

迭代器遍历集合且直接用集合删除元素的时候可能出现。

增强for循环遍历集合且直接用集合删除元素的时候可能出现。

哪种遍历且删除元素不出问题?

迭代器遍历集合但是用迭代器自己的删除方法可以解决。

使用for循环遍历并删除元素后使查询索引i自减1,或者从后向前遍历并删除指定元素,就不会出现这个问题。

示例代码如下:

publicstaticvoidmain(String[] args) {
// 1.准备数据List<String>list=newArrayList<>();
list.add("张三");
list.add("Java");
list.add("Java");
list.add("李四");
list.add("李四");
list.add("王五");
System.out.println(list); // [张三, Java, Java, 李四, 李四, 王五]// 需求:删除全部的Java信息// a.迭代器遍历删除/*        Iterator<String> it = list.iterator();while (it.hasNext()) {String ele = it.next();if (ele.equals("Java")) {//                list.remove("Java"); // 报错,并发异常,删除某个元素后迭代器查询索引会后移,不会遍历所有元素it.remove(); // 解决办法:用迭代器自己的删除方法,删除当前元素,并且迭代器查询索引不会后移,会遍历所有元素}}System.out.println(list); // [张三, 李四, 李四, 王五]*/// b.增强for循环遍历删除/*        for (String ele : list) {if (ele.equals("Java")) {list.remove("Java"); // 报错,并发异常,删除某个元素后增强for循环查询索引会后移,不会遍历所有元素}}System.out.println(list);*/// c.lambda表达式遍历删除/*        list.forEach(s -> {if (s.equals("Java")) {list.remove("Java"); // 报错,并发异常,删除某个元素后forEach的lambda表达式查询索引会后移,不会遍历所有元素}});System.out.println(list);*/// d.for循环遍历删除for (inti=0; i<list.size(); i++) {
if (list.get(i).equals("Java")) {
list.remove("Java");
// 不会报错,但是删除某个元素后for循环的查询索引i会后移,不会遍历所有元素,会漏删// 解决办法①:因此每次删除完元素后,使查询索引i自减1,使其刚好遍历所有元素i--;
            }
        }
System.out.println(list); // [张三, 李四, 李四, 王五]// 解决办法②:从后向前遍历并删除指定元素for (inti=list.size() -1; i>=0; i--) {
if (list.get(i).equals("Java")) {
list.remove("Java");
            }
        }
System.out.println(list); // [张三, 李四, 李四, 王五]    }

8.补充知识:泛型深入

8.1泛型概述

泛型:是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查。

泛型的格式:<数据类型>;注意:泛型只能支持引用数据类型

集合体系的全部接口和实现类都是支持泛型的使用的。

泛型的好处

统一数据类型。

把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为编译阶段类型就能确定下来。

泛型可以在很多地方进行定义

类后面->泛型类 方法申明上->泛型方法 接口后面->泛型接口

8.2自定义泛型类

泛型类的概述

定义类时同时定义了泛型的类就是泛型类。

泛型类的格式:修饰符 class 类名<泛型变量>{ }

此处泛型变量T可以随便写为任意标识,常见的如E、T、K、V等。

作用:编译阶段可以指定数据类型,类似于集合的作用。

泛型类的原理

把出现泛型变量的地方全部替换成传输的真实数据类型。

8.3自定义泛型方法

泛型方法的概述

定义方法时同时定义了泛型的方法就是泛型方法。

泛型方法的格式:修饰符 <泛型变量> 方法返回值 方法名称(形参列表){ }

作用:方法中可以使用泛型接收一切实际类型的参数,方法更具备通用性。

泛型方法的原理

把出现泛型变量的地方全部替换成传输的真实数据类型。

示例代码如下:

publicclassGenericDemo {
publicstaticvoidmain(String[] args) {
String[] names= {"张三", "李四", "王五"};
printArray(names);
Integer[] ages= {18, 22, 30};
printArray(ages);
    }
publicstatic<T>voidprintArray(T[] arr) {
if (arr!=null) {
StringBuildersb=newStringBuilder("[");
for (inti=0; i<arr.length; i++) {
sb.append(arr[i]).append(i==arr.length-1?"" : ",");
            }
sb.append("]");
System.out.println(sb);
        } else {
System.out.println(arr);
        }
    }
}

8.4自定义泛型接口

泛型接口的概述

使用了泛型定义的接口就是泛型接口。

泛型接口的格式:修饰符 interface 接口名称<泛型变量>{}

作用:泛型接口可以让实现类选择当前功能需要操作的数据类型

泛型接口的原理

泛型接口可以约束实现类,实现类在实现接口的时候传入自己操作的数据类型,这样重写的方法都将是针对于该类型的操作。

8.5泛型通配符、上下限

通配符:?

? 可以在“使用泛型”的时候代表一切类型。

E T K V 是在定义泛型的时候使用的。

示例代码如下:

publicclassGenericDemo {
publicstaticvoidmain(String[] args) {
ArrayList<BENZ>benzs=newArrayList<>();
benzs.add(newBENZ());
benzs.add(newBENZ());
benzs.add(newBENZ());
go(benzs);
ArrayList<BMW>bmw=newArrayList<>();
bmw.add(newBMW());
bmw.add(newBMW());
bmw.add(newBMW());
go(bmw);
ArrayList<Dog>dog=newArrayList<>();
dog.add(newDog());
dog.add(newDog());
dog.add(newDog());
//        go(dog);    }
/*** 所有车都可以参加比赛** @param cars*/publicstaticvoidgo(ArrayList<?extendsCar>cars) {
    }
}
classBENZextendsCar {
}
classBMWextendsCar {
}
classDog {
}
// 父类classCar {
}

注意:虽然BMW和BENZ都继承了Car但是ArrayList<BMW>和ArrayList<BENZ>与ArrayList<Car>没有关系的!!

泛型的上下限

? extends Car:?必须是Car或者其子类泛型上限

? super Car:?必须是Car或者其父类泛型下限

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
2月前
|
Java 大数据 API
Java Stream API:现代集合处理与函数式编程
Java Stream API:现代集合处理与函数式编程
229 100
|
2月前
|
Java API 数据处理
Java Stream API:现代集合处理新方式
Java Stream API:现代集合处理新方式
261 101
|
1月前
|
存储 算法 安全
Java集合框架:理解类型多样性与限制
总之,在 Java 题材中正确地应对多样化与约束条件要求开发人员深入理解面向对象原则、范式编程思想以及JVM工作机理等核心知识点。通过精心设计与周密规划能够有效地利用 Java 高级特征打造出既健壮又灵活易维护系统软件产品。
68 7
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
999 9
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
270 59
|
5月前
|
编译器 C语言 C++
栈区的非法访问导致的死循环(x64)
这段内容主要分析了一段C语言代码在VS2022中形成死循环的原因,涉及栈区内存布局和数组越界问题。代码中`arr[15]`越界访问,修改了变量`i`的值,导致`for`循环条件始终为真,形成死循环。原因是VS2022栈区从低地址到高地址分配内存,`arr`数组与`i`相邻,`arr[15]`恰好覆盖`i`的地址。而在VS2019中,栈区先分配高地址再分配低地址,因此相同代码表现不同。这说明编译器对栈区内存分配顺序的实现差异会导致程序行为不一致,需避免数组越界以确保代码健壮性。
105 0
栈区的非法访问导致的死循环(x64)
232.用栈实现队列,225. 用队列实现栈
在232题中,通过两个栈(`stIn`和`stOut`)模拟队列的先入先出(FIFO)行为。`push`操作将元素压入`stIn`,`pop`和`peek`操作则通过将`stIn`的元素转移到`stOut`来实现队列的顺序访问。 225题则是利用单个队列(`que`)模拟栈的后入先出(LIFO)特性。通过多次调整队列头部元素的位置,确保弹出顺序符合栈的要求。`top`操作直接返回队列尾部元素,`empty`判断队列是否为空。 两题均仅使用基础数据结构操作,展示了栈与队列之间的转换逻辑。
|
10月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
470 77
|
9月前
|
算法 调度 C++
STL——栈和队列和优先队列
通过以上对栈、队列和优先队列的详细解释和示例,希望能帮助读者更好地理解和应用这些重要的数据结构。
221 11
|
9月前
|
DataX
☀☀☀☀☀☀☀有关栈和队列应用的oj题讲解☼☼☼☼☼☼☼
### 简介 本文介绍了三种数据结构的实现方法:用两个队列实现栈、用两个栈实现队列以及设计循环队列。具体思路如下: 1. **用两个队列实现栈**: - 插入元素时,选择非空队列进行插入。 - 移除栈顶元素时,将非空队列中的元素依次转移到另一个队列,直到只剩下一个元素,然后弹出该元素。 - 判空条件为两个队列均为空。 2. **用两个栈实现队列**: - 插入元素时,选择非空栈进行插入。 - 移除队首元素时,将非空栈中的元素依次转移到另一个栈,再将这些元素重新放回原栈以保持顺序。 - 判空条件为两个栈均为空。

热门文章

最新文章