数据结构与算法(三)线性表
线性表定义
线性表( List ):零个或多个数据元素的有限序列。
首先它是一个 序列 ,其次,线性表强调是 有限的 。
前驱元素 :若A元素在B元素的前面,则称A为B的前驱元素。
后继元素 :若B元素在A元素的后面,则称B为A的后继元素。 线性表的特征
数据元素之间具有一种 一对一 的逻辑关系。 第一个数据元素没有前驱,这个数据元素被称为 头结点 ; 最后一个数据元素没有后继,这个数据元素被称为 尾结点 ; 除了第一个和最后一个数据元素外,其他数据元素有且仅有一个前驱和一个后继。
如果把线性表用数学语言来定义,则可以表示为( a1,...ai-1,ai,ai+1,...an ), ai-1 领先于 ai , ai 领先于 ai+1 ,称 ai-1 是 ai 的前驱元素, ai+1 是 ai 的后继元素。
线性表的分类
线性表中数据存储的方式可以是 顺序存储 ,也可以是 链式存储 ,按照数据的存储方式不同,可以把线性表分为顺序表和链表。 顺序表
顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用 一组地址连续的存储单元 ,依次存储线性表中的各个元素、使得线性表中再逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系。
顺序表设计
类名
SequenceList
构造方法
SequenceList(int capacity) :创建容量为 capacity 的 SequenceList 对象
成员方法 public void clear() :空置线性表
publicboolean isEmpty() :判断线性表是否为空,是返回true,否返回false
public int length() :获取线性表中元素的个数
public T get(int i) :读取并返回线性表中的第i个元素的值
public void insert(int i, E e) :在线性表的第i个元素之前插入一个值为e的数据元素。
public void insert(E e) :向线性表中添加一个元素e
public T remove(int i) :删除并返回线性表中第i个数据元素。
public int indexOf(E e) :返回线性表中首次出现的指定的数据元素的位序号,若不存在,则返回-1。
成员变量 private T[] elements :存储元素的数组
private int n :当前线性表的长度顺序表代码实现@SuppressWarnings("unchecked") public class SequenceList implements Iterable { /** * 存储元素的数组 */ private T[] elements; /** * 记录当前顺序表中的元素个数 */ private int n; /** * 创建容量为capacity的SequenceList对象 */ public SequenceList(int capacity) { // 初始化数组 this.elements = (T[]) new Object[capacity]; // 初始化长度 n = 0; } /** * 空置线性表 */ public void clear() { n = 0; } /** * 判断线性表是否为空,是返回true,否返回false */ public boolean isEmpty() { return n == 0; } /** * 获取线性表中元素的个数 */ public int length() { return n; } /** * 读取并返回线性表中的第i个元素的值 */ public T get(int i) { if (i < 0 || i >= n) { throw new RuntimeException("当前元素不存在!"); } return elements[i]; } /** * 在线性表的第i个元素之前插入一个值为t的数据元素 */ public void insert(int i, E e) { if (n == elements.length) { throw new RuntimeException("当前表已满"); } // 先把i索引处的元素及其后面的元素依次向后移动一位 for (int j = n; j > i; j--) { elements[j] = elements[j - 1]; } // 再把t元素放到i索引处 elements[i] = t; n++; } /** * 向线性表中添加一个元素t */ public void insert(E e) { if (i == elements.length) { throw new RuntimeException("当前表已满"); } if (i < 0 || i > n) { throw new RuntimeException("插入的位置不合法"); } elements[n++] = t; } /** * 删除并返回线性表中第i个数据元素 */ public T remove(int i) { if (i < 0 || i > n - 1) { throw new RuntimeException("当前要删除的元素不存在"); } // 记录i索引处的值 T current = elements[i]; // 索引i后面元素依次向前移动一位 for (int j = i; j < n - 1; j++) { elements[j] = elements[j + 1]; } // 元素个数-1 n--; return current; } /** * 返回线性表中首次出现的指定的数据元素的位序号,若不存在,则返回-1。 */ public int indexOf(E e) { if (t == null) { throw new RuntimeException("查找的元素不合法"); } for (int i = 0; i < n; i++) { if (Objects.equals(elements[i], t)) { return i; } } return -1; } }顺序表的遍历
一般作为容器存储数据,都需要向外部提供遍历的方式,因此我们需要给顺序表提供遍历方式。
在Java中,遍历集合的方式一般都是用的是 forEach 循环,如果想让我们的 SequenceList 也能支持 forEach 循环,则需要做如下操作: 让 SequenceList 实现 Iterable 接口,重写 iterator 方法; 在 SequenceList 内部提供一个内部类 SIterator ,实现 Iterator 接口,重写 hasNext 方法和 next 方法; public class SequenceList implements Iterable { // ... @Override public Iterator iterator() { return new SIterator(); } private class SIterator implements Iterator { private int cursor; public SIterator() { this.cursor = 0; } @Override public boolean hasNext() { return cursor < n; } @Override public T next() { return elements[cursor++]; } } }顺序表容量可变
在之前的实现中,当我们使用 SequenceList 时,先 new SequenceList(5) 创建一个对象,创建对象时就需要指定容器的大小,初始化指定大小的数组来存储元素,当我们插入元素时,如果已经插入了5个元素,还要继续插入数据,则会报错,就不能插入了。这种设计不符合容器的设计理念,因此我们在设计顺序表时,应该考虑它的容量的伸缩性。
考虑容器的容量伸缩性,其实就是 改变存储数据元素的数组的大小 ,那我们需要考虑什么时候需要改变数组的大小? 添加元素时扩容
添加元素时,应该检查当前数组的大小是否能容纳新的元素,如果不能容纳,则需要创建新的容量更大的数组,我们这里创建一个是原数组两倍容量的新数组存储元素。
移除元素时缩容
移除元素时,应该检查当前数组的大小是否太大,比如正在用 100 个容量的数组存储 10 个元素,这样就会造成内存空间的浪费,应该创建一个容量更小的数组存储元素。如果我们发现数据元素的数量不足数组容量的 1/4 ,则创建一个是原数组容量的 1/2 的新数组存储元素。
@SuppressWarnings("unchecked") public class SequenceList { /** * 向线性表中添加一个元素t */ public void insert(E e) { // 如果当前容量已满,那么扩容2倍 if (n == elements.length) { resize(2 * elements.length); } // ... } /** * 删除并返回线性表中第i个数据元素 */ public T remove(int i) { // ... // 如果当前元素数量小于容量的1/4,那么缩容为1/2 if (n < elements.length / 4) { resize(elements.length / 2); } return current; } /** * 根据newSize,重置elements的大小 */ public void resize(int newSize) { // 定义一个临时数组,指向原数组 T[] temp = elements; // 创建新数组 elements = (T[]) new Object[newSize]; System.arraycopy(temp, 0, elements, 0, temp.length); } }
扩缩容的原理很简单,是创建一个具有指定新容量的新数组,然后把原来的数据拷贝到新数组。 顺序表的时间复杂度get(i) :不论数据元素量 n 有多大,只需要一次 elements[i] 就可以获取到对应的元素,所以时间复杂度为 O(1) 。我们通常把具有这一特点的存储结构称为随机存取结构。 insert(int i,E e) :每一次插入,都需要把i位置后面的元素移动一次,随着元素数量N的增大,移动的元素也越多,时间复杂为 O(n) ; remove(int i) :每一次删除,都需要把i位置后面的元素移动一次,随着数据量N的增大,移动的元素也越多,时间复杂度为 O(n) ;
由于顺序表的底层由数组实现,数组的长度是固定的,所以在操作的过程中涉及到了容器扩容操作。这样会导致顺序表在使用过程中的时间复杂度不是线性的,在某些需要扩容的结点处,耗时会突增,尤其是元素越多,这个问题越明显。 顺序表的优缺点优点无需为表示表中元素之间的逻辑关系而增加额外的存储空间; 可以快速地存取表中任意位置的元素。 缺点插入和删除操作需要移动大量元素; 当线性表长度变化较大时,难以确定存储空间的容量; 造成存储空间的 碎片 。 链表
虽然顺序表的查询很快,时间复杂度为 O(1) ,但是 增删的效率是比较低的 ,因为每一次增删操作都伴随着大量的 数据元素移动 。这个问题有没有解决方案呢?
有,我们可以使用另外一种存储结构实现线性表,链式存储结构。
链表是一种物理存储单元上非连续、非顺序的存储结构,其物理结构不能只管的表示数据元素的逻辑顺序,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
链表由一系列的结点(链表中的每一个元素称为结点)组成,结点可以在运行时动态生成。
链表节点设计
类名
Node
构造方法
Node(E e, Node next) :创建 Node 对象
成员变量 E item :存储数据
Node next :指向下一个结点@NoArgsConstructor @AllArgsConstructor @Data public class Node { /** * 存储元素 */ private E item; /** * 指向下一个节点 */ private Node next; }单向链表
单向链表是链表的一种,它由多个结点组成,每个结点都由一个数据域和一个指针域组成,数据域用来存储数据,指针域用来指向其后继结点。链表的头结点的数据域不存储数据,指针域指向第一个真正存储数据的结点。
单向链表设计
类名
LinkList
构造方法
LinkList() :创建 LinkList 对象
成员方法 public void clear() :空置线性表
public boolean isEmpty() :判断线性表是否为空,是返回true,否返回false
public int length() :获取线性表中元素的个数
public E get(int i) :读取并返回线性表中的第i个元素的值
public void insert(E e) :往线性表中添加一个元素;
public void insert(int i, E e) :在线性表的第i个元素之前插入一个值为t的数据元素。
public E remove(int i) :删除并返回线性表中第i个数据元素。
public int indexOf(E e) :返回线性表中首次出现的指定的数据元素的位序号,若不存在,则返回-1。
成员变量 private Node head :记录首结点
private int n :记录链表的长度单向链表代码实现public class LinkList implements Iterable { /** * 记录首节点 */ private final Node head; /** * 记录链表的长度 */ private int n; public LinkList() { // 初始化头结点 head = new Node<>(null, null); // 初始化元素个数 n = 0; } /** * 空置线性表 */ public void clear() { head.next = null; n = 0; } /** * 判断线性表是否为空,是返回true,否返回false */ public boolean isEmpty() { return n == 0; } /** * 获取线性表中元素的个数 */ public int length() { return n; } /** * 读取并返回线性表中的第i个元素的值 */ public E get(int i) { if (i < 0 || i >= n) { throw new RuntimeException("位置不合法!"); } // 通过循环,从头结点开始往后找,依次找i次,就可以找到对应的元素 Node n = head.next; for (int index = 0; index < i; index++) { n = n.next; } return n.item; } /** * 往线性表中添加一个元素 */ public void insert(E e) { // 找到当前最后一个节点 Node n = head; // 头节点不存储数据,所以不能算作第一个元素 while (n.next != null) { n = n.next; } // 创建新节点,保存元素t // 让当前最后一个元素指向新节点 n.next = new Node<>(e, null); // 元素个数+1 this.n++; } /** * 在线性表的第i个元素之前插入一个值为t的数据元素 */ public void insert(int i, E e) { if (i < 0 || i >= n) { throw new RuntimeException("位置不合法!"); } // 找到i位置前一个节点 Node pre = head; // 头节点不存储数据,所以不能算作第一个元素 for (int index = 0; index < i; index++) { pre = pre.next; } // 找到i位置的节点 Node current = pre.next; // 创建新节点,并且新节点需要指向原来i位置的节点 // 原来i位置的前一个节点指向新节点 pre.next = new Node<>(e, current); // 元素个数+1 n++; } /** * 删除并返回线性表中第i个数据元素 */ public E remove(int i) { if (i < 0 || i >= n) { throw new RuntimeException("位置不合法"); } // 找到i位置前一个节点 Node pre = head; for (int index = 0; index < i; index++) { pre = pre.next; } // 找到i位置的节点 Node current = pre.next; // 找到i位置的下一个节点 // 前一个节点指向下一个节点 pre.next = current.next; // 元素个数 - 1 n--; return current.item; } /** * 返回线性表中首次出现的指定的数据元素的位序号,若不存在,则返回-1 */ public int indexOf(E e) { // 从头结点开始,依次找到每一个节点,取出item,和t比较,如果相同,就返回 Node n = head; for (int i = 0; n.next != null; i++) { n = n.next; if (n.item.equals(e)) { return i; } } return -1; } @Override public Iterator iterator() { return new LIterator(); } private static class Node { // 存储元素 T item; // 指向下一个节点 Node next; Node(T item, Node next) { this.item = item; this.next = next; } } }循环链表
对于单向链表,由于每个结点只存储了向后的指针,到了尾标志就停止了向后链的操作,这样,当中某一结点就无法找到它的前驱结点了。
比如,你是一业务员,家在上海,需要经常出差,行程就是上海到北京一路上的城市,找客户谈生意或分公司办理业务。你从上海出发,乘火车路经多个城市停留后,再乘飞机返回上海,以后,每隔一段时间,你基本还要按照这样的行程开展业务,如图所示:
有一次,你先到南京开会,接下来要对以上的城市走一遍,此时有人对你说,不行,你得从上海开始,因为上海是第一站。你会对这人说什么?神经病。哪有这么傻的,直接回上海根本没有必要,你可以从南京开始,下一站蚌埠,直到北京,之后再考虑走完上海及苏南的几个城市。
显然这表示你是从当中一结点开始遍历整个链表,这都是原来的单链表结构解决不了的问题。事实上,把北京和上海之间连起来,形成一个环就解决了前面所面临的困难。这就是循环链表。
从刚才的例子,可以总结出,循环链表解决了一个很麻烦的问题。 如何从当中一个结点出发,访问到链表的全部结点 。
在单向链表中,最后一个节点的指针为 NULL ,不指向任何结点,因为没有下一个元素了。要实现循环链表,我们只需要 让单向链表的最后一个节点的指针指向头结点 即可。
如果链表中没有元素,那么头结点也需要指向自己,从而形成环。
循环链表代码实现
代码实现和单向链表基本一致,只需要在插入尾结点的时候,将尾结点指向头结点即可。 public void insert(E e) { // 找到当前最后一个节点 // 头节点不存储数据,所以不能算作第一个元素 var n = head; while (n.next != null) { n = n.next; } // 创建新节点,保存元素t,让当前最后一个元素指向新节点 // 循环链表,最后一个元素指向头结点 n.next = new Node<>(e, head); // 元素个数+1 this.n++; }
同时,在构造和清空链表时,让头结点指向自己 public CycleLinkList() { // 初始化头结点 head = new Node<>(null, null); head.next = head; // 初始化元素个数 n = 0; } /** * 清空线性表 */ public void clear() { head.next = head; n = 0; }双向链表
继续刚才的例子,你平时都是从上海一路停留到北京的,可是这一次,你得先到北京开会,谁叫北京是首都呢,会就是多。开完会后,你需要例行公事,走访各个城市,此时你怎么办?
有人又出主意了,你可以先飞回上海,一路再乘火车走遍这几个城市,到了北京后,你再飞回上海。你会感慨,人生中为什么总会有这样出馊主意的人存在呢?真要气死人才行。哪来这么麻烦,我一路从北京坐火车或汽车回去不就完了吗。
我们的单链表,总是从头到尾找结点,难道就不可以正反遍历都可以吗?当然可以,只不过需要加点东西而已。
双向链表:在单链表的每个结点中,再设置一个指向其前驱结点的指针域。所以在双向链表中的结点都有 两个指针域 ,一个指向直接后继,另一个指向直接前驱。 双向链表结点设计
类名
Node
构造方法
Node(E e, Node pre, Node next) :创建Node对象
成员变量 E item :存储数据
Node next :指向下一个结点
Node pre :指向上一个结点@AllArgsConstructor private static class Node { // 存储元素 E item; // 指向上一个节点 Node pre; // 指向下一个节点 Node next; }双向链表设计
类名
DoubleLinkList
构造方法
DoubleLinkList() :创建 DoubleLinkList 对象
成员方法 public void clear() :空置线性表
public boolean isEmpty() :判断线性表是否为空,是返回true,否返回false
public int length() :获取线性表中元素的个数
public T get(int i) :读取并返回线性表中的第i个元素的值
public void insert(E e) :往线性表中添加一个元素;
public void insert(int i, E e) :在线性表的第i个元素之前插入一个值为t的数据元素。
public T remove(int i) :删除并返回线性表中第i个数据元素。
public int indexOf(E e) :返回线性表中首次出现的指定的数据元素的位序号,若不存在,则返回-1。
public T getFirst() :获取第一个元素
public T getLast() :获取最后一个元素
成员变量 private Node first :记录首结点
private Node last :记录尾结点
private int n :记录链表的长度双向链表代码实现public class DoubleLinkList implements Iterable { /** * 记录首节点 */ private final Node head; /** * 记录尾节点 */ private Node last; /** * 记录链表的长度 */ private int n; public DoubleLinkList() { // 初始化头结点 head = new Node<>(null, null, null); // 初始化尾节点 last = null; // 初始化元素个数 n = 0; } /** * 空置线性表 */ public void clear() { head.next = null; last = null; n = 0; } /** * 判断线性表是否为空,是返回true,否返回false */ public boolean isEmpty() { return n == 0; } /** * 获取线性表中元素的个数 */ public int length() { return n; } /** * 获取头结点 */ public E getFirst() { if (isEmpty()) { return null; } return head.next.item; } /** * 获取尾节点 */ public E getLast() { if (isEmpty()) { return null; } return last.item; } /** * 读取并返回线性表中的第i个元素的值 */ public E get(int i) { if (i < 0 || i >= n) { throw new RuntimeException("位置不合法!"); } // 通过循环,从头结点开始往后找,依次找i次,就可以找到对应的元素 Node n = head.next; for (int index = 0; index < i; index++) { n = n.next; } return n.item; } /** * 往线性表中添加一个元素 */ public void insert(E e) { if (isEmpty()) { // 如果链表为空 // 创建新的节点 Node newNode = new Node<>(e, head, null); // 让新节点成为尾节点 last = newNode; // 让头结点指向尾节点 head.next = last; } else { // 如果链表不为空 Node tempLast = last; // 创建新的节点 Node newNode = new Node<>(e, tempLast, null); // 当前的尾节点指向新节点 tempLast.next = newNode; // 让新节点成为尾节点 last = newNode; } // 元素个数+1 n++; } /** * 在线性表的第i个元素之前插入一个值为t的数据元素 */ public void insert(int i, E e) { if (i < 0 || i >= n) { throw new RuntimeException("位置不合法!"); } // 找到i位置的前一个节点 Node pre = head; for (int index = 0; index < i; index++) { pre = pre.next; } // 找到i位置的节点 Node current = pre.next; // 创建新节点 Node newNode = new Node<>(e, pre, current); // 让i位置的前一个节点指向新节点 pre.next = newNode; // 让i位置的前一个节点变为新节点 current.pre = newNode; // 元素个数+1 n++; } /** * 删除并返回线性表中第i个数据元素 */ public E remove(int i) { if (i < 0 || i >= n) { throw new RuntimeException("位置不合法"); } // 找到i位置前一个节点 Node pre = head; for (int index = 0; index < i; index++) { pre = pre.next; } // 找到i位置的节点 Node current = pre.next; // 找到i位置的下一个节点 Node next = current.next; // i位置的前一个节点的下一个节点指向i位置的下一个节点 pre.next = next; // i位置的下一个节点的前一个节点指向i位置的前一个节点 next.pre = pre; // 元素个数 - 1 n--; return current.item; } /** * 返回线性表中首次出现的指定的数据元素的位序号,若不存在,则返回-1 */ public int indexOf(E e) { // 从头结点开始,依次找到每一个节点,取出item,和t比较,如果相同,就返回 Node n = head; for (int i = 0; n.next != null; i++) { n = n.next; if (n.item.equals(e)) { return i; } } return -1; } @Override public Iterator iterator() { return new LIterator(); } @AllArgsConstructor private static class Node { // 存储元素 E item; // 指向上一个节点 Node pre; // 指向下一个节点 Node next; } private class LIterator implements Iterator { private Node n = head; @Override public boolean hasNext() { return n.next != null; } @Override public E next() { n = n.next; return n.item; } } }链表的时间复杂度get(int i) :每一次查询,都需要从链表的头部开始,依次向后查找,随着数据元素N的增多,比较的元素越多,时间复杂度为 O(n) ; insert(int i, E e) :每一次插入,需要先找到i位置的前一个元素,然后完成插入操作,随着数据元素N的增多,查找的元素越多,时间复杂度为 O(n) ; remove(int i) :每一次移除,需要先找到i位置的前一个元素,然后完成插入操作,随着数据元素N的增多,查找的元素越多,时间复杂度为 O(n) 。
相比较顺序表,链表插入和删除的时间复杂度虽然一样,但仍然有很大的优势,因为链表的物理地址是不连续的,它 不需要预先指定存储空间大小 ,并且在存储过程中 不涉及到扩容等操作 ,同时它并没有涉及的元素的交换。
相比较顺序表,链表的查询操作性能会比较低。
因此,如果我们的程序中 查询操作比较多,建议使用顺序表,增删操作比较多,建议使用链表 。
投资近两亿元修建两年多通车不到一月上虞这座桥为何要翻修?视频加载中6月29日,历时2年多建设的绍兴市上虞区舜江大桥拼宽建设工程通车了,这个民生工程建成后将极大缓解城区交通拥堵。然而,通车不到一个月,不少市民就发现大桥主桥沥青路面出现鼓包
为了打击中国新能源车,美国要与韩国为敌?最近笔谈君看到一件事,还挺魔幻的。作为美国坚定盟友的韩国和欧盟,可能要被美国出卖了,目的是为了在新能车上能和中国有一争之力。这可不是笔谈君瞎说的,就在前段时间,拜登签署通过了通胀削
花西子品牌分析报告互联网平台报告微博小红书天猫淘宝知乎百度公众号视频号小程序微信快手B站抖音营销传播报告品牌营销社群营销内容营销达人营销社媒营销私域营销电商行业报告跨境电商微信电商社群电商社区电商快
孔蒂我们踢了场不错的比赛,但如果你不进球那么就不会赢在已经结束的欧冠小组赛第3轮的比赛中,热刺在客场00战平法兰克福,目前热刺积4分暂时位居D组第二的位置。赛后,热刺主帅孔蒂接受了采访谈到了本场比赛球队的表现。尽管没有拿下比赛的胜利
突发他宣布辞职!刚刚,拜登遭背刺,一点面子也不给美国中国基金报泰勒大家好,美股港股一番史诗级大涨之后,5日晚间,迎来调整,上个交易日道指涨了800多点,今夜一度跌了400点,不知道接下来两个交易日,该不会跌到A股开盘吧一起来看看5日
黯然离场?NBA新赛季即将开始,联盟还有九位球星仍未找到下家优胜劣汰,适者生存。这句话同样适用于NBA赛场,NBA休赛期至今,随着施罗德哈雷尔格里芬相继拿到新合约,NBA自由球员又少了几位,但仍有一部分球员在自由市场游荡,迟迟未找到归宿。如
女乒全胜晋级八强!孙颖莎重回一单位置,世界冠军失掉李隼信任头条创作挑战赛女乒晋级八强有球员已掉队!2022年的成都世乒赛已经进入了淘汰赛的争夺,中国女乒在18决赛面对匈牙利队,这是一场没有悬念的比赛,但是国乒教练组依然派出了最强的阵容,出
反对声中,英政府突然180度大转弯英国首相特拉斯上台执政后不久,就宣布了一系列新经济政策。当地时间9月23日,英国政府公布了自1972年以来最激进的减税方案。然而,这些措施不但在国内引发反对声浪,还严重扰乱了国际金
互联网双子星敲边鼓胡锡进,捶破鼓司马南互联网是个大舞台,既然是舞台就必须有演员。之前大家处于泛娱乐化时代,追逐各种明星新闻和私生活。如今大家追随各种意见领袖,还经常因为立场大同激烈开撕。目前国内互联网形成了双子星,他们
这三款手机值得入手十月份这三款手机值得入手第一款OPPOFindX5优势外观外观设计辨识度颇高影像5000万像素双主摄马里亚纳影像芯片哈苏调色,拍照和视频录制能力出色续航80W有线快充30W无线快充
恭喜!世乒赛八强决出五席,兄弟队双双晋级,法国女团爆冷被淘汰2022年10月5日,世乒赛继续进行,女团赛场爆出冷门,法国队输给斯洛伐克队,曾战胜伊藤美诚的袁嘉楠两战皆败,令人大跌眼镜,中国香港队中国台北队双双晋级,可喜可贺。男团日本30巴西
超越苏炳添!宝岛飞人杨俊瀚创造中国男子百米本赛季最佳成绩文羊城晚报全媒体记者柴智10月3日,在中国台湾省新北城市杯田径公开赛上,中国台北选手杨俊瀚在男子100米决赛中以10秒12的成绩夺冠,是其职业生涯的第二好成绩,超越苏炳添在尤金世锦
统治力!中国女乒头名晋级淘汰赛小组赛仅丢一小局10月4日,成都世乒赛团体赛小组赛最后一个比赛日,此前收获小组赛三连胜的中国女乒迎来了马来西亚队的挑战。今天李隼指导安排陈梦轮休,昨天出场的陈幸同也没有得到出场的机会,孙颖莎王曼昱
女富豪何巧女有钱到美国捐96亿,却无力偿还200亿国内债务如果您喜欢这篇文章,请点击右上方的关注。感谢您的支持和鼓励,希望能给您带来舒适的阅读体验。随着深交所的一声钟响,东方园林正式上市,而它的创始人何巧女,更是被业界誉为中国园林第一人。
三十年华正青春中联重科日日新来源人民网人民日报过去十年,是中国工程机械高质量创新发展全面跨越的十年,中联重科股份有限公司(简称中联重科)也经历了从20岁到30岁不断拔节向上的快速发展。三十年征程,中联重科秉持
正视差距需要勇气,人民币成全球第4大货币,占比仍不足美元110美国除了拥有强大的军事实力,也有着收割全球经济的美元金融霸权。不过随着美联储接连加息,美元的霸主地位动摇,人民币支付份额反而逐步上涨。全球三大支付货币不久前,央行发布一份报告,其中
广西制造业冠军一年营收超过了千亿,柳工玉柴五菱位居其后广西企业与企业家联合会前不久发布了2022广西制造业企业100强名单,从企业的营业收入来看,有一家收入超过千亿,营业收入百亿以上的有26家。下面根据这份榜单公布的数据简单做个盘点。
机关事业单位退休人员,有人养老金补发了4万元,这是咋回事?机关事业单位退休人员,有人的养老金补发了4万元,这是咋回事?答案来了机关事业单位退休人员,目前是跟企业退休人员一样,参与到每年的养老金上涨,并没有太大差异。不过其中有一类人,那就是
与十月在秋光处言和秋渐深,意渐浓,草木枝叶在日渐的消瘦,浓密疏淡间全是萎黄干枯,草丛也不见青绿。那些走着走着就能遇见的花开,和所有给予这个世界美丽的风景,在如今都成满目苍夷留下的只有落寞与凋零。纵使
人到中年,就别在这几件事上较劲了倏忽已至中年。你是在哪一个瞬间,突然感觉到这一点呢?有人说,是某天对着镜子梳头发时,骤然多了起来的白发有人说,是看到照片上的自己,腹部居然有了游泳圈,还有的人则说,是那种每天一睁开
难与易作者文军近年来,我以自诩修行者的状态在推动自己改变与成长,我身上有地方的人文积累的不足,有自己几十年养成的个人陋习,我深知差距还很大,所以,我乐此不疲的每天分享,希望逼着自己成长,
人生如旅,得一知己,足矣茫茫人海,人能相遇,已是不易心若相知,更需珍惜。人生如旅,得一知己,足以慰风尘。知己,是心有灵犀的懂得,是一份心照不宣的爱,是一份有着特殊内涵的陪伴。人生如旅,得一知己,足矣。知己