线性数据结构
jer2021
2021-01-25 15:45:27
# 线性数据结构
| 数据结构 | 优点 | 缺点 |
| :----------: | :----------: | :----------: |
| 数组 | 插入快 | 查找慢 ,删除慢 ,大小固定只能存储单一元素 |
| 有序数组 | 比无序数组查询快 | 插入慢 ,删除慢 ,大小固定只能存储单一元素 |
| 栈 | 提供后进先出的存储方式 | 存储其他项慢 |
| 队列 | 提供先进先出的存储方式 | 存储其他项 |
| 链表 | 插入快 ,删除快 | 查找慢 |
| 二叉树 | 如果数是平衡的 ,则查找,插入,删除快 |删除算法复杂 |
| 2-3-4树 | 查找,插入,删除快 ,树总是平衡的 | 算法复杂|
| 哈希表 | 如果关键字已知则存储极快 | 删除慢 ,如果不知道关键字存储慢,对储存空间使用不充足 |
| 堆 | 插入 ,删除快 ,对最大数据储存快 | 对其他数据存取慢 |
| 图 |对现实世界建模 | 有些算法慢而复杂 |
| 红黑树 | 查找,插入,删除快 ,树总是平衡的 | 算法复杂 |
二叉堆
![](https://visualgo.net/img/gif/heap.gif)
链表
![](https://visualgo.net/img/gif/list.gif)
树状数组
![](https://visualgo.net/img/gif/fenwicktree.gif)
- ## 指针
### 1. 指针变量(int *p) 与普通变量(int a)的关系
```cpp
p ------ &a //&为取地址运算符
*p ------ a //*为间接运算符
*p=3 ------ a=3
```
### 2. 指针变量定义
```cpp
int *p=NULL;
```
定义了一个指针p ,p指向一个内存空间 ,里面存放着一个内存地址。现在赋值为NULL(为0 ,表示特殊的空地址)。
### 3. 给指针变量p赋值
```cpp
int a=3;
p=&a
```
即把a变量的内存地址给了p
*p的值为3 ,p为地址
### 4. 指针变量初始化
| | 方法 | 说明 |
| :----------- | :----------- | :----------- |
| 1 | int *p=NULL; | NULL为特殊的地址0 ,叫零指针 |
| 2 | int *p=&a;| p初始化为变量a的地址 |
| 3 | int*p=new(int) | 申请一个空间给p ,*p内容不确定 |
### 5. 指向结构体变量的指针
**一个结构体变量的指针就是该变量所占据的内存段的起始地址。可以设一个指针变量,用来指向一个结构体变量,此时,该指针变量的值是结构体变量的起始位置。**
**使用指针变量访问结构体成员示例**
```cpp
#include <cstdio>
#include <iostream>
using namespace std;
struct student{
string name;
int age;
int fx;
};
student x={"xiaoming" ,13 ,100};
student *p;
int main()
{
p=&x;
cout << x.name << endl;
cout << (*p).age << endl;
cout << p->fx << endl;
}
```
输出
```
xiaoming
13
100
--------------------------------
Process exited after 0.05083 seconds with return value 0
请按任意键继续. . .
```
注:p->age 相当于 x.age。
## 链表
### 单链表
#### 1. **单链表结构体定义**
```cpp
struct name{
(类型)data
struct name *next;
//name为结构体名称 ,next指向下一个节点的指针
};
```
#### 2. **基本操作**
- **初始化**
```
/*
| 头指针L | NULL |
*/
L=new name;
L->next=NULL;
```
- 创建
![](https://cdn.luogu.com.cn/upload/image_hosting/3zeqar6j.png)
- 取值,查找
![](https://cdn.luogu.com.cn/upload/image_hosting/xp7kzfng.png)
```cpp
P=L->next;j=1;
P=P->next;j=2;
```
- 插入
![](https://cdn.luogu.com.cn/upload/image_hosting/23w6egiq.png)
- 删除
![](https://cdn.luogu.com.cn/upload/image_hosting/lcpmgm9z.png)
**相关代码**
```cpp
#include<iostream>
#include<string>
using namespace std;
typedef struct LNode {
int data; //结点的数据域
struct LNode *next; //结点的指针域
}LNode, *LinkList; //LinkList为指向结构体LNode的指针类型
void CreateList_R(LinkList &L)//尾插法创建单链表
{
//输入n个元素的值,建立带表头结点的单链表L
int n;
LinkList s, r;
L=new LNode;
L->next=NULL; //先建立一个带头结点的空链表
r=L; //尾指针r指向头结点
cout <<"请输入元素个数n:" <<endl;
cin>>n;
cout <<"尾插法(正序)创建单链表..." <<endl;
while(n--)
{
s=new LNode;//生成新结点
cin>>s->data; //输入元素值赋给新结点的数据域
s->next=NULL;
r->next=s;//将新结点s插入尾结点r之后
r=s;//r指向新的尾结点s
}
}
LinkList findmiddle(LinkList L)
{
LinkList p,q;
p=L; //p为快指针,初始时指向L
q=L; //q为慢指针,初始时指向L
while(p!=NULL&&p->next!=NULL)
{
p=p->next->next;//p为快指针一次走两步;
q=q->next; //q为慢指针一次走一步
}
return q;//返回中间结点指针
}
void Listprint_L(LinkList L) //单链表的输出
{
LinkList p;
p=L->next;
while (p)
{
cout<<p->data<<"\t";
p=p->next;
}
cout<<endl;
}
int main()
{
LinkList L,mid;
cout<<"创建单链表L:"<<endl;
CreateList_R(L);
cout<<"单链表数据为:"<<endl;
Listprint_L(L);
mid=findmiddle(L);
cout<<"单链表中间结点数据为:"<<mid->data<<endl;
return 0;
}
```
### 双向链表
- 插入
![](https://cdn.luogu.com.cn/upload/image_hosting/muhm9a4d.png)
```cpp
P->pior->next=s;
S->pior=P->pior;
S->next=p;
P->next=S;
```
- 删除
![](https://cdn.luogu.com.cn/upload/image_hosting/wn1vz0y9.png)