今日学习2022/03/08线性表
线性表
是由同类型数据元素构成的有序序列的线性结构
元素个数称为表长度。
数据对象集
线性表是n个同类型元素构成的有序序列。
操作集
List MakeEmpty():初始化一个空线性表L
ElementType FindKth(int K,List L):根据位序K,返回L线性表内的相应元素
Int Find (ElementType X,List L):在线性表L中查找X的第一次出现的位置
void Insert(ElementType X,int i,List L):在线性表L中的第i个元素的位置插入X元素。
void Delet(int i,List L):删除线性表L中的第i个元素
int Length(List L):返回线性表的长度n。
1. 线性表的顺序存储的实现(数组形式)
利用数组的连续存储空间顺序存放线性表的各个元素
线性表的结构定义
//方式一
typedef struct LNode *List;
struct LNode{
ElementType Data[MAXSIZE];
int Last;
};
struct LNode L;
List Ptrl;
//访问下表为i的元素
L.Data[i]或者Ptrl->Data.[i];
//线性表的长度
L.Last+1或者Ptrl->Last+1;
初始化(建立空顺序表)
List MakeEmpty()
{
List Ptrl;
Ptrl = (List)malloc(sizeof(struct LNode));
Ptrl->Last = -1;
return Ptrl;//返回Ptrl指针的地址
}
查找 返回Ptrl线性表的X元素
ElementTpye Find(ElementType X,List Ptrl)
{
for (int i = 0;i<Ptrl.length();i++)
{
//从i元素开始寻找
int i = 0;
while(i<= Ptrl->Last && Ptrl->Data[i]!=X)
{i++};
//退出循环的方式两种:找到与没找到
if(i>Ptrl->Last) return -1;//没有找到X元素,返回-1
else return i;//找到后返回存储位置
}
插入(第i 个位置(1~n+1)插入元素X)
void Insert(ElementType X,int i,List Ptrl)
{
//存在忽略问题
//**忘记判断Ptrl链表是否已经被元素充满**
if(Ptrl->Last == MaxSize-1)
{
printf("表已存满");
return;
}
//**插入的位置是否合法**
if(i <1 || i>Ptrl->Last+2)
{
printf("位置不合法哦");
return;
}
//指向链表Ptrl的最后一个位置
//使其从最后一个元素开始往后挪动一位,然后将i位置空出来存放元素X
int j = Ptrl->Last;
while(j!=i)
{
Ptrl->Data[j+1] =Ptrl->[j];
j--;
}
if(j==i-1)
{
Ptrl->Data[i-1] = X;
}
Ptrl->Last++;//多加入元素需要将Last指向的最后元素加一
return;
}
查找 返回Ptrl线性表的X元素
void Delet(int i,List Ptrl)
{
//首先判断删除位置的i元素的位置是否合法
if(i<1||i>Ptrl->Last+1)
{
printf("不存在该元素位置");
return;
}
int j = i;
for (j;j<Ptrl->Last;j++)
{
Ptrl->Data[j-1] = Ptrl->Data[j];
}
Ptrl->Last--;
return ;
}
2. 线性表的链式存储的实现(链表形式)
不要求逻辑上相连的元素在物理上也相连只是通过链建立起元素与元素之间的逻辑上的连接关系。插入,删除不需要移动元素,只需要移动“链条”即可
链表结构的定义
typedef struct LNode*List;
struct LNode{
ElementType Data;
List Next;//链接链表下一个元素的位置,next这样的一个指针
};
struct LNode L;
List Ptrl;
链表的求解表长
int Length(List Ptrl)
{
//首先定义一个指向链表的头指针
List p = Ptrl;
//定义变量,返回指针的位置
int j =0;
//判断p不为None那么链表的位置继续递增
while(p) //在P没有可继续指向的Next指针后,Next为空值了,退出循环
{
p = p->Next;
j++
}
return j;
}
链表中元素的查找
//(按序号查找)
List FindKth(int K,List Ptrl)
{
//p是一个临时的链表指针
//注意此时的指针类型是List
List p = Ptrl;
int i = 1;
while(p!= NULL && i<K)
{
p=p->Next;
i++;
}
if(i == K) //找到了第K个指针
{
return P;
}
else //返回结果为空
{
return NULL;
}
}
//按照给定的数值查找
List Find (int X,Lis Ptrl)
{
List p = Ptrl;
while(p!= NULL && P->Data != X)
{
P=P->Next;
}
if(P->Data = X)
{
return p;
}
else
{return NULL;}
}
链表中元素的插入操作
在链表中插入元素的主要步骤:
- 定义一个新的节点
- 将元素的数值赋值给节点
- 使新节点的Next指针指向要插位的后一个节点位置
- 将插入位置的前一节点的Next指针指向新节点位置
链表中不存在零位置,最小位置为1
void Insert(ElementType X,int i,List Ptrl)
{
List p,s;
//如果要插入的位置是头节点
if(i == 1)
{
s = (List)malloc(sizeof(struct() LNode)*1);
s->Data = X;
s->Next = Ptrl;
return s; //s为头节点对应的指针位置
}
//如果插入位置在1后面
p =FindKth(i-1,Ptrl);
//如果第i-1个元素不存在的话,则不能插入
if(p == NULL)
{
printf("节点参数错误");
return NULL;
}
else
{
s= (List)molloc(sizeof(struct LNode));
s->Data = X;
s->Next = P->Next;
p->Next = s;
return Ptrl;
}
}
链表中元素的删除操作
先找到链表要删除位置的第i-1个节点,并且用p指针指向该节点
再用S指针指向要被删除的节点(p的下一个节点)
然后修改指针,删除s所指的节点
最后释放s所指的节点的空间
List Delet(int i,List Ptrl)
{
List p,s;
if(i == 1)
{
s = Ptrl;
if(Ptrl!= NULL)
{Ptrl = Ptrl->next;}
else return NULL;
free (s);
return Ptrl;
}
p = FindKth(i-1,Ptrl);
if(p== NULL)
{printf("节点不存在");return NULL}
else if(p->Next = NULL)
{printf("下一个节点不存在";return NULL)
else
{
s=p->Next;
p->Next = s->Next;
free(s);
return Ptrl;
}
}
广义表
广义表
广义表是线性表的推广
线性表是n个单元素组成
广义表可以是单元素也可以是另一个广义表
//GList = struct GNode*
typedef struct GNode *GList;//用GList 代替结构体广义表
struct GNode
{
int Tag; //0表示节点是单元素,1表示节点是广义表
union{
ElementType Data;
Glist sublist;
}URegion;
GList Next;
}
多重链表
多重链表:链表中的节点可能同时隶属于多个链
节点的指针域存在多个,Next,SubList等等
但是包含两个指针与的链表并不一定是多重链表
树和图应用
左上角的Term是多重链表的入口,代表:4行5列的矩阵
分别用两个Next指针指向行的Head节点以及列的Head节点。
同时行列分别的节点又指向Term节点(存放数据)
用Tag标识域来区分头节点(Head)和非0元素节点
同时Head节点与Term节点(不同通过Union来串联在一起)
Head和Term都存在两个节点(down和head)
异点
Term存在RowCol以及Value但是Head通过Next指针链接union