线性结构
(一)线性表
它不仅仅是数组或者链表,它是一个结构体,结构体里面包含有数据数组和线性表的大小。
顺序存储
使用数组进行存储
1)首先需要定义一个结构体,包含数据数组和线性表的大小(使用last作为标记)。
注意事项:
1、初始化线性表就是为它开辟一片空间。
2、PtrL->last中的->针对指向结构体的指针,而成员访问符.是针对于结构体变量。
3、在进行插入操作的时候应该考虑到原本的空间是否已经满、插入的位置是否合法。
4、并且增加和删除元素之后,记得更新last的值。
//线性表的顺序存储结构//
//建立之前需要建立一个结构体//
typedef struct LNode *List;
struct LNode{//整个线性表被包含在这个结构体中//
Elementype Data[MAXSIZE];
int last//用于存储顺序表的大小//
}L;
List PtrL;//用PtrL指向结构体//
//操作一:建立一个顺序表,初始化//
List MakeEmpty()
{
PtrL=(List)malloc(sizeof(struct LNode));
PtrL->last=-1;
return PtrL;
}
//操作二:查找元素//
int Find(int X;List PrtL)
{
int i=0;
while(i<=PtrL->last&&PtrL->Data[i]!=X)
{
i++;
}
if(i>PtrL->last)
return -1;
else
return i;
}
//操作三:插入——先移动再插入//
void Insert(int X,int i,List PrtL)//在第i个位置插入X
{
if(PrtL->last==MAXSIZE-1)
{
pritnf("表已经满了");
return;
}
if(i<1||i>PrtL->last+2)//判断插入的位置是否合法
{
printf("位置不合法");
return;
}
int j;
for(j=PrtL->last;j>=i-1;j--)
{
PrtL->Data[j+1]=PrtL->Data[j];
}
PrtL->Data[i-1]=X;
PrtL->last++;
return;
}
//操作四:删除元素//
void Delete(int i,List PrtL)//删除第i个位置的元素//
{
if(i<1||i>PrtL->last+1)
{
printf("不存在第i个元素")
return;
}
int j;
for(j=i-1;j<=PrtL->last;j++)
{
PrtL->Data[i-1]=PrtL->Data[i];
}
PrtL->last--;//删完之后别忘了将last值减去 //
return;
}
链式存储
使用链表进行存储
1)仍然需要定义一个结构体,里面包含数据和指向下一个结点的指针。
注意事项:
1、对于一切插入操作,首先应想到插入内容的本质,比如插入结点,那么首先就得构建一个结点,分配空间。
2、对于链表,插入的位置有区别,链表头和其他位置有不同,需单独考虑。
3、在进行删除操作的时候也应该注意表头和其他位置的不同,并且需要有一个指针指向被删除的结点,然后 free。
//线性表的链式存储结构//
typedef struct LNode *List;
struct LNode{
int data;
List next;
}L;
List PrtL;
//因为是自定义类型,List本身就是一个指向结点的指针所以不是*PrtL
//操作一:求表长//
int length(List PrtL)
{
int i=0;
List p=PrtL;//p指向表中的第一个结点//
while(PrtL!=NULL)
{
i++;
PrtL=PrtL->next;
}
return i;
}
//操作二:查找//
//按照序号查找//
List FindKth(int K,List PrtL)
{
List p=PrtL;
int i=0;
while(i<k&&p!=NULL)
{
i++;
p=p->next;
}
if(i==k)
return p;
else
return NULL;
}
//按照值查找//
List Find(ElementType X,List PrtL)
{
List p=PrtL;
while(p)
{
if(p->data==X)
return p;
p=p->next;
}
return NULL;
}
//操作三:插入//
List Insert(ElementType X,int i,List PrtL)//在第i个位置插入元素X//
{
List s=malloc(sizeof(struct LNode));//构建预插入结点//
s->data=X;
if(i==1)
{
s->next=PrtL;
return s;
}
List p=PrtL;//指向第一个结点//
int j=0;
while(j<i-2)
{
j++;
p=p->next;
if(!p)
return NULL;
}
s->next=p->next;
p->next=s;
return PrtL;
}
//操作四:删除//
List Delete(int i,List PrtL)
{
List p,s;
if(i==1)//如果是删除第一个结点//
{
List s=PrtL;
if(!PrtL)
return NULL;
else
PrtL=PrtL->next;
free(s);//一定要有free的操作//
return PrtL;
}
p=FindKth(i-1,PrtL);
if(!p)
return NULL;
else if(!p->next)
return NULL;
else
{
s=p->next;//首先将结点定位好//
p->next=s->next;
free(s);
return PrtL;
}
}
(二)堆栈
与线性表一样,堆栈也是一个结构体,里面包含一个一维数组和存储栈顶元素位置的变量。
顺序存储
使用数组进行堆栈的存储
注意事项:
1、在使用堆栈的时候应当先进行初始化操作。
2、入栈相当于插入,所以应判断堆栈是否满了。
3、出栈相当于删除,应判断删除的元素是否合法,也就是是否堆栈是空的。
4、遇到先pop出来top标记再减掉的情况可以,写在同一个表达式中。
//堆栈的顺序存储结构//
typedef struct SNode *Stack;
struct SNode{
ElementType Data[MAX];
int top;
};
//操作一:入栈//
void Push(Stack PrtS,ElementType item){
PrtS=malloc(sizeof(struct SNode));
PrtS->top=-1;//初始化堆栈//
if(PrtS->top==MAX-1)
{
printf("堆栈已满");
return;
}
else
{
PrtS->Data[++(PrtS->top)]=item;
return;
}
}
//操作二:出栈//
ElementType Pop(Stack PrtS){
if(PrtS->top==-1)
return ERROR;
else
return PrtS->Data[(PrtS->top)--];
}
链式存储
使用链表进行存储
1)同样使用结构体,但是结构体里面存储的就是数据和指向下一节点的指针,不是数据数组。
注意事项:
1、结点或者链表在进行初始化的时候应当将next指针置为NULL。
2、堆栈的链式存储top指针应该放在表头,head和第一个数据节点之间,top如果放在尾端,则删除的时候无法找到前端指针。
//堆栈的链式存储结构//
typedef struct SNode *Stack;
struct SNode{
ElementTpye Data;
Stack next;
};
//操作一:初始化//
Stack Creat(){
Stack S;//指向结点//
S=malloc(sizeof(struct SNode));
S->next=NULL;
return S;
}
//操作二:判断是否为空//
int IsEmpty(Stack S){
return (S->next==NULL);//为空的话就返回整数1//
}
//操作三:入栈//
void Push(ElementType X,Stack S){
struct SNode New=malloc(sizeof(struct SNode));
New->Data=X;
New->next=NULL;//初始化结点//
New->next=S->next;
S->next=New;
return;
}
//操作四:出栈//
ElementType Pop(Stack S){
struct SNode *Delete;//删除元素,需要释放空间,则需要定义一个指针//
if(!S->next)
return ERROR;
else
{
Delete=S->next;
S->next=Delete->next;
free(Delete);
return Delete->Data;
}
}
(三)队列
同样使用结构体包装整个队列
顺序存储
使用数组存储,结构体中包含一个一维数组和front和rear标记
//队列的顺序存储//
typedef struct QNode *Queue;
struct QNode{
ElementType Data[MAX];
int front;
int rear;
};
//操作一:初始化//
Queue creat(){
Queue Q=malloc(sizeof(struct QNode));
front=-1;
rear=-1;
return Q;
}
//操作二:入队,出队//
void Add(Queue PtrQ,ElementType item){
if("队列满了")
return;
else
PtrQ->Data[++(PtrQ->rear)]=item;
}
ElementType Pop(Queue PtrQ){
if(PtrQ->front==PtrQ->rear)
{
printf("队列是空的");
return;
}
else
return PtrQ->Data[(PtrQ->front)++];
}
链式存储
链式存储需要两个结点,数据结点包含数据和指向下一结点指针,另一结点包含front和rear指针。
注意事项:
1、链式存储时front和rear分别位于表头和表尾,因为表头方便删除。
//队列的链式存储结构//
struct Node{
ElementType data;
struct Node *next;
};
struct QNode{
struct Node *front;
struct Node *rear;
};
typedef struct Node *Queue
//操作一:出队(无头结点)//
ElementType Delete(Queue PrtQ){
struct Node *pop;
pop=QNode->front;
if("队列为空")
return EORROR;
else
{
pop->data=QNode->front->data;
QNode->front=QNode->front->next;
free(pop);
return pop->data;
}
}