1、数组
---- 数组是一种顺序存储的数据结构,逻辑上相邻的两个元素在物理上也是相邻的。每个元素占用的内存相同,可以通过下标访问。
如果要增加或删除一个元素,需要移动大量元素。但可以快速访问数据 ---- (存取速度快)。
2、链表
---- 链表是一种链接(链式)存储的数据结构,逻辑上相邻的两个元素在物理上一般是不相邻的。
相邻元素之间的访问必须通过指针实现。
如果要访问链表中的一个元素,需要从第一个元素(链表头)开始,直到查找到需要访问的元素的位置。
但是如果要删除或者插入一个元素,只需要修改元素的指针就可以了。
3、在链接存储中,每个元素(结点)至少需要包含两个方面的信息:
---- 1)元素本身的信息(叫数值/数据域)
---- 2)实现元素之间链接关系的指针信息(叫指针域)
若每个元素只有一个指针域,用于指向其后继结点,这样的链表叫线性单向链表,简称单向链表或单链表。
若每个元素有两个指针域,分别用于指向其前驱和后继结点,这样的链表叫线性双向链表,简称双向链表或双链表。
头指针是指向链表中第一个结点(或为头结点或为首元结点)的指针;
头结点是在链表的首元结点之前附设的一个结点;数据域内只放空表标志和表长等信息
首元素结点是指链表中存储线性表中第一个数据元素a1的结点.
4、简单链表
简单链表是单链表中最简单的一种情况,成员中至少有一个数值域用来表示元素信息,有一个指针用来指向一个结构体。
下面举个例子:定义3个结点,然后链成一个简单链表,并输出每个结点的信息。
#include <iostream>
using namespace std;
typedef struct node
{
char ch;
struct node *next;
}Node;
int main()
{
Node a,b,c,*p;
a.ch = 'a';
b.ch = 'b';
c.ch = 'c';
a.next = &b;
b.next = &c;
c.next = NULL;
p = &a;//pointer to the first node
while(p!=NULL)
{
printf("%c ",p->ch);
p = p->next;
}
system("pause");
return 0;
}
输出:a b c
5、链表和数组的区别(面试常问)
---- 1)从逻辑结构角度看:
数组需要事先指定其长度(即元素个数),不能适应数据动态地增减的情况。即在使用数组之前,就必须对数组的大小进行确定。
当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费。 数组中插入、删除数据项时,需要移动其它数据项。
链表是动态分配的,可以适应数据动态地增减的情况。要时可以用new/malloc分配内存空间,不需要时用delete/free将已分配的空间释放。
不会造成内存空间浪费,且可以方便地插入、删除数据项。
---- 2)从内存存储角度: 顺序存储和链式存储
数组从栈中分配空间,对于程序员方便快速,但是自由度小。(静态)
链表从堆中分配空间,自由度大,但是申请管理比较麻烦。
---- 3)从访问效率的角度
数组中的数据在内存中是顺序存储的,而链表是随机存储的。数组的随机访问效率很高,可以直接定位,但插入、删除操作的效率比较低。
链表在插入、删除操作上相对数组有很高的效率。但如果要访问链表中的某个元素的话,那就得从表头逐个遍历,直到找到所需要的元素为止。
所以,链表的随机访问效率比数组低。
---- 4)是否越界问题
链表不存在越界问题,但是数组存在越界问题。数组便于查询,链表便于插入和删除。
数组节省空间但是长度固定。链表占用更多的存储空间。