文章目录
线性表的定义和基本操作
线性表的定义
线性表:具有相同数据类型的数据元素的有限序列。
表头元素,表尾元素,(直接)前驱,(直接)后继
特点:
- 元素个数有限;
- 每个元素数据类型相同,占用存储空间相同;
- 线性表是逻辑结构,而顺序表和链表是存储结构;
- 随机访存,通过首地址和序号可以用时间 O ( 1 ) O(1) O(1)找到元素;
- 存储密度高,因为每个结点只存储数据元素;
- 逻辑上相邻的元素物理上也相邻,插入和删除需要时间 O ( n ) O(n) O(n);
顺序表
顺序表的定义
静态分配存储空间
#def MaxSize 100
typedef struct SqList {
int data[MaxSize];
int length;
}SqList;
动态分配存储空间
#def InitSize 100
typedef struct {
int* data;
int maxSize, length;
}SeqList;
SeqList L;
L.data = new int[InitSize]
顺序表的基本操作
注意顺序表的元素序号从1开始,而实现时使用的数组下标从0开始。
插入
//将元素e插入到i位置,返回是否插入成功
bool SqInsert(SqList& L, int i, int e)
{
//判断i的范围是否合法
if (i<1 || i>L.length + 1)
return false;
//判断存储空间是否已满
if (L.length >= MaxSize)
return false;
//将i号及之后的元素后移
for (int j = L.length; j >= i; j--)
L.data[j] = L.data[j - 1];
//将元素i设置为e
L.data[i - 1] = e;
L.length++;
return true;
}
删除
//删除第i个元素,用引用变量e返回
bool SqDelete(SqList& L, int i, int& e)
{
//判断i的范围是否合法
if (i<1 || i>L.length)
return false;
e = L.data[i - 1];
//将i个元素之后的所有元素前移
for (int j = i; j < L.length; j++)
L.data[j - 1] = L.data[j];
L.length--;
return true;
}
按值查找(定位某个元素)
//查找值为e的元素序号
int SqLocate(SqList L, int e)
{
int i;
for (i = 0; i < L.length; i++)
if (L.data[i] == e)
return i + 1;
return 0;
}
链表
单链表
定义
数据域存放数据元素,指针域存放后继结点的地址。
typedef struct LNode {
int data;
struct LNode* next;
}LNode, * LinkList;
头插法
//头插法
LinkList ListHeadInsert(LinkList &L)
{
LNode* s;
int x;
//L = (LinkList)malloc(sizeof(LNode));
L = new LNode;
L->next = NULL;
cin >> x;
while (x != 9999) {
s = (LinkList)malloc(sizeof(LNode));
s->data = x;
s->next = L->next;
L->next = s;
cin >> x;
}
return L;
}
尾插法
//尾插法
//1.建立头指针、尾指针,分配头结点;
//2.循环分配新结点,插到最后(加一根线);
//3.尾结点next置为NULL;
LinkList ListTailInsert(LinkList& L)
{
//L = (LinkList)malloc(sizeof(LNode));
L = new LNode;
LNode* s;
LNode* t = L;
int x;
L->next = NULL;
cin >> x;
while (x != 9999) {
//s = (LinkList)malloc(sizeof(LNode));
s = new LNode;
s->data = x;
t->next = s;
t = s;
cin >> x;
}
t->next = NULL;
return L;
}
按序号查找结点
// 按序号查找结点
LNode* LGetElem(LinkList L, int i)
{
LNode* r = L;
int j = 0;//头结点视为0号结点
while (r != NULL && j < i) {
r = r->next;
j++;
}
return r;
}
按值查找结点
//按值查找结点
LNode* LLocateElem(LinkList L, int e)
{
LNode* r = L;
while (r != NULL && r->data != e)
r = r->next;
return r;
}
插入结点
//插入元素e到pos位置
bool LPositionInsert(LinkList& L, int e, int pos)
{
LNode* priorNode = LGetElem(L, pos - 1);
if (priorNode == NULL)
return false;
LNode* newNode = new LNode;
newNode->data = e;
newNode->next = priorNode->next;
priorNode->next = newNode;
return true;
}
删除结点
//删除pos位置的结点,并返回结点数据元素
int LPositionDelete(LinkList& L, int pos)
{
LNode* priorNode = LGetElem(L, pos - 1);
if (priorNode == NULL || priorNode->next == NULL)
return 9999;
LNode* delNode = priorNode->next;
int r = delNode->data;
priorNode->next = delNode->next;
delete delNode;
return r;
}
求表长
//求链表长度
int GetLength(LinkList L)
{
int length = 0;
LNode* p = L->next;
while (p != NULL) {
p = p->next;
length++;
}
return length;
}
双链表
相比单链表,访问、插入、删除前驱结点的复杂度均为 O ( 1 ) O(1) O(1)(单链表为 O ( n ) O(n) O(n))。
定义
typedef struct DNode {
int data;
struct DNode* prior, * next;
}DNode, * DLinkList;
插入结点
//插入元素e到pos位置
bool DPositionInsert(DLinkList& DL, int e, int pos)
{
DNode* priorNode = DGetElem(DL, pos - 1);
if (priorNode == NULL)
return false;
DNode* newNode = new DNode;
//如图所示,四步操作必须按顺序进行
newNode->data = e;
newNode->next = priorNode->next;
if (priorNode->next != NULL)
newNode->next->prior = newNode;
newNode->prior = priorNode;
priorNode->next = newNode;
return true;
}
删除节点
//删除pos位置的结点,并返回结点数据
int DPositionDelete(DLinkList& DL, int pos)
{
DNode* priorNode = DGetElem(DL, pos - 1);
if (priorNode == NULL || priorNode->next == NULL)
return 9999;
DNode* delNode = priorNode->next;
int r = delNode->data;
if (delNode->next != NULL)
delNode->next->prior = priorNode;
priorNode->next = delNode->next;
delete delNode;
return r;
}
循环链表
循环单链表
与单链表相比,表的尾结点的尾指针指向头结点。
尾指针:提高在表尾插入元素操作效率
时间复杂度 | 在表头插入元素 | 在表尾插入元素 |
---|---|---|
头指针 | O ( 1 ) O(1) O(1) | O ( n ) O(n) O(n) |
尾指针 | O ( 1 ) O(1) O(1) | O ( 1 ) O(1) O(1) |
循环双链表
与双链表相比,表的尾结点的尾指针指向头结点;当表为空表时,头结点的头尾指针都指向头结点。
静态链表
借助数组实现的链表
特点:
- 与顺序表一样需要预先分配存储空间;
- 以 n e x t = = 1 next==1 next==1为表结束标志;
- 插入、删除操作只需要移动指针不需要修改元素;
#define MaxSize 100
typedef struct{
int data;
int next
}SLinkList[maxSize];