#include<iostream>
#include<iomanip>
#include<cmath>
#include<string.h>
#include<string>
#include <ctime>
#include<cstdlib>
#include<algorithm>
#include<cstdio>
#include<queue>
using namespace std;
//线性表知识点
// 定义:具有相同数据类型的n个数据元素的有限序列
// 特点:1.元素个数有限 2.有逻辑顺序 3.数据元素相同
// 线性表基本操作:初始化,长度,增删查,打印,销毁
// InitList(&L)
// Length(L)
// LocateElem(L,e)
// GetElem(L,i)
// ListInsert(&L,i,e)
// ListDelete(&L,i,&e)
// PrintList(L)
// Empty(L)
// DestoryList(L)
// 顺序表:逻辑顺序和物理顺序相同
// 实现:本质就是数组
#define MaxSize 10
typedef struct //静态分配
{
int data[MaxSize];//可以是任意类型表示元素
int length;//表示当前长度
}SqList;
//初始化
void InitList(SqList &L)
{
for(int i =0;i<MaxSize;i++)cin>>L.data[i];
L.length = 0;
}
//动态分配
typedef struct //静态分配
{
int *data;//可以是任意类型表示元素
int Max;//最大长度
int length;//表示当前长度
}SqList;
//初始化
void InitList(SqList &L)
{
L.data = new int [MaxSize];
L.length = 0;
L.Max = MaxSize;
}
//增加动态数组长度
void IncreaseSize(SqList &L,int add_len)
{
int *p = L.data;//记住原本的地址
L.data = new int[L.Max+add_len];//开辟总长度
for(int i =0;i<L.Max;i++) L.data[i] = p[i];//移植原本的数据
L.Max+=add_len;//更新max
delete []p;//释放原本的空间
}
//顺序表特点:
// 1.随机访问:可以再o(1)找到第i个元素
// 2.存储密度高,每个节点只存储数据元素并没有存下一个节点位置(不需要)
// 3.拓展容量不方便,只能使用动态
// 4.插入和删除不方便
//插入元素(平均为o(n))
bool ListInsert(SqList &L,int i,int e)//位置和元素
{
if(i<1||i>L.length+1)return false;
if(L.length>=MaxSize)return false;//装满了
for(int j = L.Max;j>=i;j--)L.data[j] = L.data[j-1];//第i-1个元素后面的数字后移,可以理解为从第i+1个数字开始获得前面的值
L.data[i-1] = e;
L.length++;
return true;
}
//删除操作平均为o(n)
bool ListDelete(SqList &L,int i,int &e)//位置和返回元素值
{
if(i<1||i>L.length)return false;
e = L.data[i-1];//记录删除元素
for(int k =i-1;k<L.length-1;k++)L.data[k] = L.data[k+1];//从i位置前移
L.length--;
return true;
}
//按位查找o(1)
int GetElem(SqList L,int i)//位置
{
return L.data[i-1];
}
//按值查找o(n)
int LocateElem(SqList L,int e)//值->返回位置
{
for(int i =0;i<L.length;i++)
{
if(L.data[i]==e)return i+1;//返回位置
}
return 0;//表示没有找到
}
//链表
// 定义:节点包含数据元素和指向下一个节点的指针
// 定义
typedef struct LNode
{
int data;
LNode* next;
}LNode,*LinkList;//一个是结构体,一个是指向结构体的指针(就是链表)
//初始化不带头节点
bool InitList(LinkList &L)//没有开辟空间
{
L = NULL;//防止野指针
return true;
}
//判断单链表是否为空
bool Empty(LinkList &L)
{
if(L==NULL)return true;
else return false;
}
//初始化带头节点
bool InitList(LinkList &L)
{
L = new LNode;//开辟空间
if(L==NULL)return false;//内存不够
L->next = NULL;
return true;
}
//判断单链表是否为空
bool Empty(LinkList &L)
{
if(L->next==NULL)return true;
else return false;
}
//头指针和头节点的区别:
// 1.头指针都指向第一个节点
// 2.有头结点是第一个节点,通常不存储数据元素
// 大多数情况都使用带头节点不然会更麻烦
//单链表插入
//带头结点
bool ListInsert(LinkList &L,int i,int e)//位序和值
{
if(i<1)return false;
//扫描找到前面一个的位置
LNode* p;
int j =0;
p = L;//从头节点0开始找
while(p!=NULL&&j<i-1)//找到i-1个节点
{
j++;
p = p->next;
}
if(p==NULL)return false;//不合法
LNode*s = new LNode;//开辟一个空间
s->next = p->next;
p->next = s;//将s连接到p后
s->data = e;
return true;
}
//不带头节点(考虑特殊位置1,剩下和带头的相同)
bool ListInsert(LinkList &L,int i,int e)//位序和值
{
if(i<1)return false;
//扫描找到前面一个的位置
if(i==1)
{
LNode*s =new LNode;//开辟空间
s->next = L;
L = s;//这两步不一样
s->data = e;
return true;
}
LNode* p;
int j =0;
p = L;//从头节点0开始找
while(p!=NULL&&j<i-1)//找到i-1个节点
{
j++;
p = p->next;
}
if(p==NULL)return false;//不合法
LNode*s = new LNode;//开辟一个空间
s->next = p->next;
p->next = s;//将s连接到p后
s->data = e;
return true;
}
//后插函数
bool InsertNextNode(LNode *p,int e)//p节点后面插入e
{
if(p==NULL)return false;
LNode*s = new LNode;//开辟空间
if(s==NULL)return false;
s->next = p->next;
s->data = e;
p->next = s;
return true;
}
//前插函数
// 有头指针o(n)
bool InsertPriorNode(LinkList &L,LNode *p,int e)
{
//找到p前一个节点
LNode *ptr = L;
while(ptr->next!=p&&ptr!=NULL)
{
ptr = ptr->next;
}
if(ptr==NULL)return false;
LNode *s = new LNode;//开辟空间
if(s==NULL)return false;
s->next = ptr->next;
s->data = e;
ptr->next = s;
return true;
}
//没有头节点o(1)
bool InsertPriorNode(LNode *p,int e)
{
if(p==NULL)return false;
LNode *s = new LNode;
if(s==NULL)return false;
//先后插入
s->next = p->next;
p->next = s;
//交换数据
s->data = p->data;
p->data = e;
return true;
}
//按位删除o(n)
//带头结点
bool ListDelete(LinkList &L,int i,int &e)//头指针,位序,删除值
{
if(i<1)return false;
//找到前一个节点
int j =0;
LNode *p = L;
while (p!=NULL&&j<i-1)
{
j++;
p = p->next;
}
if(p==NULL)return false;
if(p->next==NULL)return false;//没有该节点
//删除
LNode *q = p->next;//i节点
p->next = q->next;
e = q->data;
delete q;//释放空间
}
//不带头节点(特殊考虑i=1)
bool ListDelete(LinkList &L,int i,int &e)//头指针,位序,删除值
{
if(i<1)return false;
if(i==1)
{
if(L==NULL)return false;
//记录第一个节点
LNode *q = L;
e = q->data;//记录值
L = L->next;//舍弃掉第一个节点
delete q;//释放空间
return true;
}
//找到前一个节点
int j =0;
LNode *p = L;
while (p!=NULL&&j<i-1)
{
j++;
p = p->next;
}
if(p==NULL)return false;
if(p->next==NULL)return false;//没有该节点
//删除
LNode *q = p->next;//i节点
p->next = q->next;
e = q->data;
delete q;//释放空间
return true;
}
//指定节点删除
// 带头结点,选择o(1)算法,有最后一个的缺陷
bool DeleteNode(LNode *p)
{
if(p==NULL)return false;
LNode *q = p->next;//后面一个节点
p->data = q->data;//复制元素
delete q;//释放空间
return true;
}
//按位查找
LNode *GetElem(LinkList &L,int i)
{
if(i<1)return NULL;//判断
int j =0;
LNode *p = L;
while(p!=NULL&&j<i)//获得i节点
{
j++;
p = p->next;
}
return p;
}
//封装后
// 按位插入
bool ListInsert(LinkList &L,int i,int e)
{
if(i<1)return false;
LNode *p = GetElem(L,i-1);//获得前面节点
return InsertNextNode(p,e);//向后插入
}
//按值查找
LNode *GetElem(LinkList &L,int e)
{
LNode*p = L;
while (p!=NULL)
{
if(p->data==e)return p;
p = p->next;
}
}
//求表的长度
// 带头结点
int Length(LinkList L)
{
int j =0;//统计长度
LNode *p = L;
while(p->next!=NULL)
{
j++;
p = p->next;
}
return j;
}
//不带头结点
int Length(LinkList L)
{
int j =1;
LNode *p = L;
if(p==NULL)return 0;
while(p->next!=NULL)
{
j++;
p = p->next;
}
return j;
}
//单链表的建立
//尾插法
LinkList List_TailInsert(LinkList &L)
{
int x;//数据
L = new LNode;//建立头结点
LNode *s,*r =L;
cin>>x;
while(x!=9999)//9999表示结束
{
s = new LNode;//开辟空间
s->data = x;//载入数据
r->next = s;//确立连接
r = s;//移动r
cin>>x;
}
r->next = NULL;//尾结点置空
return L;
}
//头插法
LinkList List_TailInsert(LinkList &L)
{
int x;
L = new LNode;
L->next = NULL;//首节点置空
LNode *s;//新节点
while(x!=9999)
{
s = new LNode;
s->data = x;
s->next = L->next;
L->next = s;
cin>>x;
}
return L;
}
//双链表
//结点类型
typedef struct DNode
{
int data;
DNode *prior,*next;// 前后驱指针
}DNode,*DLinklist;
//初始化
bool InitDLinkList(DLinklist &L)
{
L = new DNode;//开辟一个空间
if(L==NULL)return false;
L->next = NULL;
L->prior = NULL;
return true;
}
//插入
bool InsertNextNode(DNode *p,DNode *s)//在p结点后面插入s结点
{
if(p==NULL||s==NULL)return false;
s->next = p->next;
if(p->next!=NULL)p->next->prior = s;
p->next = s;
s->prior = p;
}
//删除
bool DeleteNode(DNode *p)
{
if(p==NULL)return false;
DNode*q = p->prior;//获得前面结点
DNode*r = p->next;//获得后面结点
q->next = r;
if(r!=NULL)r->prior = q;
delete p;
return true;
}
//循环单链表
//初始化
bool InitDLinkList(LinkList &L)
{
L = new LNode;//开辟空间
if(L==NULL)return false;
L->next = L;
return true;
}
//静态链表
//可以理解为结构体数组
//结构体存放数据和下一个数据的下标
struct Node
{
int data;
int next;//下一个数组的下标
}SLinkList[MaxSize];
线性表——知识点
于 2024-02-14 15:26:11 首次发布