一,栈
A.顺序存储
内容:此线性表采用顺序存储,实现了初始化、建表、查找、删除、打印,清空,销毁,返回前去后继等功能。
---------------函数功能实现------------------
//构造一个空栈S
int InitStack(SqStack *S)
{
printf("\n*****创建空栈*****\n");
(*S).base = (int *)malloc(STACK_INIT_SIZE*sizeof(int));
if(!(*S).base) {printf("\n--空间申请失败--\n");return ERROR;}
(*S).top = (*S).base;
(*S).stacksize = STACK_INIT_SIZE;
printf("\n--空栈创建成功--\n");
return OK;
}
//销毁栈S:S不再存在
int DestroyStack(SqStack *S)
{
printf("\n*****销毁栈*****\n");
free((*S).base);
(*S).top = (*S).base=NULL;//将元素清空
(*S).stacksize=0;//没有元素,则stacksize置0
printf("\n--销毁成功--\n");
return TRUE;
}
//置空栈:把S置为空栈
int ClearStack(SqStack *S)
{
printf("\n*****清空栈*****\n");
(*S).top = (*S).base;//即栈顶和栈底指针为同一位置
printf("\n--清空成功--\n");
return TRUE;
}
//判空栈:若栈S为空S栈,则返回TRUE,否则返回FALSE
int StackEmpty(SqStack *S)
{
printf("\n*****栈的判空*****\n");
if((*S).top == (*S).base) {printf("\n--栈为空--\n");return TRUE;}
else{printf("\n--栈不为空--\n");return FALSE;}
return FALSE;
}
//栈长:返回S的元素个数,即栈的长度
int StackLength(SqStack *S)
{
printf("\n*****计算长度*****\n");
printf("\n--栈的长度为:%d--\n",(*S).top - (*S).base);
return (*S).top - (*S).base;//栈顶指针指向最后一个元素的下一位置
}
//若栈S不空,则用e返回S的栈顶元素;否则返回 ERROR
int GetTop(SqStack *S,int e)
{
printf("\n*****查找栈顶*****\n");
if((*S).top == (*S).base) {printf("\n--栈为空,无法查找栈顶--\n");return ERROR;}
e=*((*S).top-1);
printf("\n--栈顶为:%d--\n",e);
return e;
}
//进栈:插入元素e为新的栈顶元素
int Push(SqStack *S,int e)
{
printf("\n*****从栈顶进栈*****\n");
if((*S).top - (*S).base >= (*S).stacksize)//数据过多,栈满,增加存储空间
{
(*S).base=(int *)realloc((*S).base,((*S).stacksize+STACKINCREMENT)*sizeof(int));
//realloc增加空间之后,栈内数据不变,但会被复制到新的基址中,原内存块会被realloc释放
//如果可以直接在原先的内存块的后面增加数据的话,realloc就不用上面的那种方式了,但是前提是空间足够
if (!(*S).base) return ERROR;
(*S).top = (*S).base + (*S).stacksize;//扩容成功后,按照惯例栈顶指针指向最后一个元素的下一位置
(*S).stacksize += STACKINCREMENT;//将定义的存储空间追加空间
}
*(*S).top++=e;//将参数数据逐个进栈
printf("\n--%d进栈--\n",e);
return OK;
}
//退栈:若栈S不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
int Pop(SqStack *S,int e)
{
printf("\n*****从栈顶出栈*****\n");
if((*S).top == (*S).base) {printf("\n--栈为空--\n");return ERROR;}
e=*(--((*S).top));//将栈顶指针前移一位,然后将当前位置上的数据返回给e,完成删除栈顶元素的操作
printf("\n--%d出栈--\n",e);
return OK;
}
//输出栈:从栈底到栈顶依次输出栈内元素
int StackTraverse(SqStack *S)
{
printf("\n*****遍历输出*****\n\n");
int *p = NULL;
int length = 0;
int i;
if((*S).top == (*S).base && (*S).base != NULL)
{
printf("\n--栈为空,无法遍历输出--\n");
}
if((*S).base == NULL)
{
printf("\n--栈不存在,无法遍历输出--\n");
return ERROR;
}
length = StackLength(S);
printf("\n\n位置 | ");
for(i = 1;i <= length;i++)
{
if(i == 1)
printf("栈底");
else
{
printf("\t");
if(i == length)
printf("栈顶");
}
}
printf("\n-----------------------------------------------\n");
printf("数据 | ");
if((*S).top != (*S).base) //栈不为空时
{
for(p= (*S).base;p <= (*S).top-1;p++)
printf("\t%d",*p);
}
printf("\n");
return OK;
}——————————栈顺序存储主函数(测试)————————————
#include "G.h"
void main()
{
SqStack myS;
SqStack *S = &myS;
int e;
//创建空栈
InitStack(S);
//判空
StackEmpty(S);
//计算长度
StackLength(S);
//进栈:插入数据
printf("\n请输入进栈数据:\n");
scanf("%d",&e);
while(e != 0)
{
Push(S,e);
printf("\n请输入进栈数据:\n");
scanf("%d",&e);
}
StackEmpty(S);
//StackLength(S);
//输出栈内数据
StackTraverse(S);
//找出栈顶元素
GetTop(S,e);
//退栈
Pop(S,e);
GetTop(S,e);
StackLength(S);
StackTraverse(S);
//清空栈内数据
ClearStack(S);
StackEmpty(S);
//StackLength(S);
GetTop(S,e);
StackTraverse(S);
//销毁栈
DestroyStack(S);
StackTraverse(S);
}
B.链式存储
————————函数实现—————————
void InitStack(DAT *S)
{
printf("\n*****创建空栈*****\n");
(*S).base = (sqStack *)malloc(sizeof(sqStack));
(*S).top = (*S).base;
printf("\n--创建空栈成功--\n");
}
void ClearStack(DAT *S)
{
printf("\n*****清空栈*****\n");
sqStack *p = (*S).base;
while(p != (*S).top)
{
printf("\n--清除数据:%d--\n",p -> data);
p = p -> next;
free((*S).base);
(*S).base = p;
}
printf("\n--清空栈成功--\n");
}
void DestroyStack(DAT *S)
{
printf("\n*****销毁栈*****\n");
sqStack *p = (*S).base;
while(p != (*S).top)
{
p = p -> next;
free((*S).base);
(*S).base = p;
}
(*S).base = NULL;//将数据清空之后,还要将栈的基底指针置空
printf("\n--销毁栈成功--\n");
}
void Push(DAT *S,int e)
{
printf("\n*****数据进栈*****\n");
printf("\n请输入进栈数据:\n");
scanf("%d",&e);
while(e != 0)
{
sqStack *p = NULL;//p指针的作用为记录当前栈顶的位置,方便新栈顶的定位(即p的下一个)
p = (*S).top;
(*S).top -> data = e;
//printf("\n--%d进栈--\n",*((*S).top));
//printf("\n--top的当前位置1:%d--\n",((*S).top));
(*S).top = (sqStack *)malloc(sizeof(sqStack));
p -> next = (*S).top;
//printf("\n--top的当前位置2:%d--\n",((*S).top));
printf("\n请输入进栈数据:\n");
scanf("%d",&e);
}
}
int Pop(DAT *S,int e)
{
printf("\n*****数据出栈*****\n");
if((*S).base == (*S).top){printf("\n--栈为空,无法将数据出栈--\n");return FALSE;}
sqStack *p = (*S).base;
while(p -> next != (*S).top) p = p -> next;
e = p -> data;
printf("\n--%d出栈--\n",e);
(*S).top = p;
return OK;
}
int GetTop(DAT *S,int e)
{
printf("\n*****查找栈顶*****\n");
if((*S).base == (*S).top){printf("\n--栈为空,无法查找栈顶元素--\n");return FALSE;}
sqStack *p = (*S).base;
while(p -> next != (*S).top) p = p -> next;
e = p -> data;
printf("\n--栈顶元素为:%d--\n",e);
return e;
}
int StackEmpty(DAT *S)
{
printf("\n*****栈的判空*****\n");
if((*S).base == (*S).top){printf("\n--栈为空--\n");return TRUE;}
else{printf("\n--栈不为空--\n");return FALSE;}
}
int StackLength(DAT *S)
{
printf("\n*****栈的长度*****\n");
int length = 0;
sqStack *p = (*S).base;
while(p != (*S).top)
{
length++;
p = p -> next;
}
printf("\n--栈的长度为:%d--\n",length);
return length;
}
int StackTraverse(DAT *S)
{
printf("\n*****遍历输出*****\n");
if((*S).base == (*S).top && (*S).base != NULL){printf("\n--栈为空,无法遍历输出--\n");return FALSE;}
if((*S).base == NULL){printf("\n--栈不存在,无法遍历输出--\n");return FALSE;}
sqStack *p = (*S).base;
printf("\n位置 | 栈底");
printf("\n----------------------------------------------\n");
printf("数据 | ");
while(p != (*S).top)
{
printf("%d ", p -> data);
p = p -> next;
}
printf("栈顶");
printf("\n");
}
—————————————————主函数———————————————#include "K.h"
void main()
{
int e;
DAT myS;
DAT *S = &myS;
//创建空栈
InitStack(S);
//判空
StackEmpty(S);
//进栈
Push(S,e);
//返回栈顶元素
GetTop(S,e);
//计算栈的长度
StackLength(S);
StackEmpty(S);
//遍历输出
StackTraverse(S);
//出栈
Pop(S,e);
StackTraverse(S);
GetTop(S,e);
StackEmpty(S);
//清空栈
ClearStack(S);
StackTraverse(S);
StackEmpty(S);//销毁栈
DestroyStack(S);
StackTraverse(S);
}
二.队列
A.顺序存储
内容:此线性表采用链式存储,实现了初始化、建表、查找、删除、打印,清空,销毁,返回前去后继等功能。
————————————队列基本函数实现—————————————
int InitQueue(sqQueue *Q)
{
printf("\n*****创建空队*****\n");
(*Q).base = (int *)malloc(MAXQSIZE * sizeof(int));
if(!(*Q).base) exit(OVERFLOW);
(*Q).front = (*Q).rear = 0;
(*Q).queuesize = MAXQSIZE;//初始分配空间为3
printf("\n--空队创建成功--\n");
return OK;
}
void DestroyQueue(sqQueue *Q)
{
printf("\n*****销毁队列*****\n");
free((*Q).base);//存储数据的空间完全释放
(*Q).base = NULL;//指针置空
(*Q).queuesize = 0;//当前分配的空间数目置空
printf("\n--销毁成功--\n");
}
void ClearQueue(sqQueue *Q)
{
printf("\n*****清空队列*****\n");
(*Q).front = (*Q).rear = 0;
(*Q).queuesize = 0;//为了防止在清空数据之后再将数据进队是发生错误,将当前分配的空间数置零
printf("\n--数据清空成功--\n");
}
int EnQueue(sqQueue *Q,int e)
{
printf("\n*****数据进队*****\n");
if((*Q).rear - (*Q).front == (*Q).queuesize)//数据个数等于当前分配的空间数目的话,队列满载
{
(*Q).base=(int*)realloc((*Q).base,((*Q).queuesize + QUEUEINCREMENT)*sizeof(int));
if(!(*Q).base) exit(OVERFLOW); //存储分配失败
(*Q).queuesize += QUEUEINCREMENT; //队空间大小增加
printf("\n--系统空间不足,自动增加2个单位--\n");
}
(*Q).base[(*Q).rear] = e;
printf("\n--%d进队--\n",(*Q).base[(*Q).rear]);
(*Q).rear++;
return e;
}
int DeQueue(sqQueue *Q,int e)
{
printf("\n*****数据出队*****\n");
if((*Q).front == (*Q).rear){printf("\n--队列为空,无法出队--\n");return FALSE;}
e = (*Q).base[(*Q).front];
(*Q).front++;
(*Q).queuesize--;//分配空间减一
printf("\n--%d出队--\n",e);
return e;
}
int GetHead(sqQueue *Q,int e)
{
printf("\n*****查找队头*****\n");
if((*Q).front == (*Q).rear && (*Q).base != NULL){printf("\n--队列为空,无法查找队头元素--\n");return FALSE;}
if((*Q).base == NULL){printf("\n--队列不存在,无法查找队头元素--\n");return FALSE;}
e = (*Q).base[(*Q).front];
printf("\n--队头元素为:%d--\n",e);
return e;
}
int QueueLength(sqQueue *Q)
{
if((*Q).base == NULL) {printf("\n--队列不存在,无法计算长度--\n");return FALSE;}
printf("\n*****计算长度*****\n");
printf("\n--队列长度为:%d--\n",(*Q).rear - (*Q).front);
return (*Q).rear - (*Q).front;
}
int QueueEmpty(sqQueue *Q)
{
printf("\n*****队列判空*****\n");
if((*Q).front == (*Q).rear){printf("\n--队列为空--\n");return TRUE;}
else{printf("\n--队列不为空--\n");return FALSE;}
}
int QueueTraverse(sqQueue *Q)
{
printf("\n*****队列输出*****\n\n");
int i;
if((*Q).front == (*Q).rear && (*Q).base != NULL){printf("\n--队列为空--\n\n");}
if((*Q).base == NULL){printf("\n--队列不存在,无法遍历输出--\n");return FALSE;}
printf("位置 | ");
printf("队头");
printf("\n-----------------------------------------------\n");
printf("数据 | ");
for(i = (*Q).front;i < (*Q).rear;i++)
{
printf("%d ",(*Q).base[i]);
}
printf("队尾\n\n");
return OK;
}
—————————主函数——————————
#include "L.h"
void main()
{
int e;
sqQueue myQ;
sqQueue *Q = &myQ;
//创建空队
InitQueue(Q);
//队列判空
QueueEmpty(Q);
//计算长度
QueueLength(Q);
//查找队头
GetHead(Q,e);
//数据进队
printf("\n请输入进队数据:\n");
scanf("%d",&e);
while(e != 0)
{
EnQueue(Q,e);
printf("\n请输入进队数据:\n");
scanf("%d",&e);
}
//遍历输出
QueueEmpty(Q);
QueueLength(Q);
QueueTraverse(Q);
GetHead(Q,e);
//数据出队
DeQueue(Q,e);
QueueLength(Q);
QueueTraverse(Q);
GetHead(Q,e);
//销毁
//DestroyQueue(Q);
//QueueTraverse(Q);
//清空
ClearQueue(Q);
QueueTraverse(Q);
GetHead(Q,e);
}
B.链式存储
————————————队列链式函数实现——————————————
//创建空队
int InitQueue(dat *Q)
{
printf("\n*****进入创建空队函数*****\n");
(*Q).front = (*Q).rear = (DAT *)malloc(sizeof(DAT));
if(!(*Q).front) {printf("\n--空队创建失败--\n");exit(OVERFLOW);}
(*Q).front -> next = NULL;
printf("\n--空队创建成功--\n");
return OK;
}
//录入数据
dat *CreatQueue(dat *Q)
{
printf("\n*****进入数据录入函数*****\n");
int n,i;
printf("\n请输入你要录入的数据个数:\n");
scanf("%d",&n);
for(i = 1;i <= n;i++)
{
DAT *p = (DAT *)malloc(sizeof(DAT));
printf("\n请输入数据:\n");
scanf("%d",&p -> data);
p -> next = NULL;
(*Q).rear -> next = p;
(*Q).rear = p;
//printf("--队头:%d--",*((*Q).front -> next));
//printf("--队尾:%d--\n",*((*Q).rear));
}
return Q;
}
//销毁队列
void DestroyQueue(dat *Q)
{
printf("\n*****进入销毁队列函数*****\n");
while((*Q).front)
{
(*Q).rear = (*Q).front -> next;
free((*Q).front);
(*Q).front = (*Q).rear;
}
printf("\n--销毁成功--\n");
}
//清空队列
void ClearQueue(dat *Q)
{
//画图可以帮助理解
printf("\n*****进入清空队列函数*****\n");
DAT *p = (*Q).front -> next;//p的初始位置为队头(有数据)
while((*Q).front -> next)
{
(*Q).rear = p;
p = (*Q).rear -> next;//移动到最后,p = NULL
printf("\n--%d出队--\n",*((*Q).rear));
free((*Q).rear);
(*Q).rear = (*Q).front;
(*Q).front -> next = p;//到最后p = NULL,所以刚好满足循环跳出的条件,且数据完全已被清空,表头指针也被保留了下来
}
free(p);
printf("\n--清空完成--\n");
}
//队列判空
int QueueEmpty(dat *Q)
{
printf("\n*****进入队列判空函数*****\n");
if((*Q).front == (*Q).rear)
{printf("\n--队列为空--\n");return TRUE;}
else
{printf("\n--队列不为空--\n");return FALSE;}
}
//计算队列长度
int QueueLength(dat *Q)
{
printf("\n*****进入计算长度函数*****\n");
int length = 0;
DAT *p = (*Q).front -> next;
while(p != NULL)
{
length++;
p = p -> next;
}
printf("\n--队列的长度为:%d--\n\n",length);
return length;
}
//返回队头
int GetHead(dat *Q,int e)
{
printf("\n*****进入返回队头函数*****\n");
if((*Q).front == (*Q).rear){printf("\n--队列为空,无法查找队头元素--\n");return(FALSE);}
DAT *p = (*Q).front -> next;
e = p -> data;
printf("\n--队头为:%d--\n",p -> data);
return e;
}
//进队
void EnQueue(dat *Q,int e)
{
printf("\n*****进入进队函数*****\n");
DAT *p = (DAT * )malloc(sizeof(DAT));
if(!p) exit(OVERFLOW);
p -> data = e;
p -> next = NULL;
(*Q).rear -> next = p;//用表尾指针进行增减操作更具有可靠性(因为表尾指针可以随着数据的增减而移动,而表头指针不行)
(*Q).rear = p;
}
//出队
int DeQueue(dat *Q,int e)
{
printf("\n*****进入出队函数*****\n");
DAT *p = (*Q).front -> next;
DAT *q = p -> next;
e = p -> data;
printf("\n--%d出队--\n",e);
(*Q).front -> next = q;
if((*Q).front -> next == NULL)
(*Q).front = (*Q).rear;
return e;
}
//遍历输出
int QueueTraverse(dat *Q)
{
printf("\n*****进入遍历输出函数*****\n");
if((*Q).front == (*Q).rear && (*Q).front != NULL){printf("\n--队列为空--\n");return(FALSE);}
if((*Q).front == NULL){printf("\n--队列不存在--\n");return(FALSE);}
int length,i;
DAT *p = (*Q).front -> next;
length = QueueLength(Q);
printf("位置 |");
printf("队头");
printf("\n--------------------------------------\n");
printf("数据 | ");
while(p != NULL)
{
printf("%d ",p -> data);
p = p -> next;
}
printf("队尾");
printf("\n");
return OK;
}
——————————————主函数——————————————————
#include "J.h"
void main()
{
int e;
dat myQ;
dat *Q = &myQ;
//创建空队
InitQueue(Q);
//判空
QueueEmpty(Q);
//录入数据
Q = CreatQueue(Q);
//遍历输出
QueueTraverse(Q);
//销毁队列
//DestroyQueue(Q);
//QueueTraverse(Q);
//清空队列
ClearQueue(Q);
QueueTraverse(Q);
//返回队头
GetHead(Q,e);
//进队
printf("\n请输入你要进队的数据:\n");
scanf("%d",&e);
while(e != 0)
{
EnQueue(Q,e);
printf("\n请输入你要进队的数据:\n");
scanf("%d",&e);
}
QueueTraverse(Q);
//出队
DeQueue(Q,e);
QueueTraverse(Q);
}
三.循环队列
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define NULL 0
#define OVERFLOW -2
#define MAXSIZE 5
typedef struct
{
int *base;
int front;
int rear;
}SqQueue;
int InitQueue(SqQueue *Q)
{
printf("\n*****创建空队列*****\n");
(*Q).base=(int *)malloc(MAXSIZE*sizeof(int));
if(!(*Q).base) exit(OVERFLOW);
(*Q).front = (*Q).rear = NULL;
printf("\n--循环队列的默认空间为:4--\n");
printf("\n--空表创建成功--\n");
return OK;
}
int creatQueue(SqQueue *Q)
{
printf("\n*****录入数据*****\n");
int n,i;
printf("\n请输入你要存储的数据个数:\n");
scanf("%d",&n);
printf("\n请输入数据:\n");
for(i = 0;i < n;i++)
{
scanf("%d",&(*Q).base[i]);
(*Q).rear = (i+1)%MAXSIZE;
if(((*Q).rear+1)%MAXSIZE == (*Q).front)
{
printf("\n--队列已满--\n");return FALSE;
}
}
printf("\n--队头位置:%d--\n",(*Q).front);
printf("\n--队尾位置:%d--\n",(*Q).rear);
return TRUE;
}
int DestroyQueue(SqQueue *Q)
{
printf("\n*****销毁队列*****\n");
free((*Q).base);
(*Q).base = NULL;
printf("\n--销毁成功--\n");
return OK;
}
int ClearQueue(SqQueue *Q)
{
printf("\n****清空队列*****\n");
(*Q).rear = (*Q).front = NULL;
printf("\n--清空成功--\n");
return OK;
}
int QueueLength(SqQueue *Q)
{
printf("\n*****计算队列长度*****\n");
printf("\n--队列长度为:%d--\n", ((*Q).rear-(*Q).front+MAXSIZE)%MAXSIZE);
return ((*Q).rear-(*Q).front+MAXSIZE)%MAXSIZE;
}
int QueueEmpty(SqQueue *Q)
{
printf("\n*****队列是否为空*****\n");
if((*Q).front==(*Q).rear) {printf("\n--队列为空--\n");return TRUE;} //队列空
else return ERROR;
}
int GetHead(SqQueue *Q,int e)
{
printf("\n*****返回队头元素*****\n");
if((*Q).front==(*Q).rear) {printf("\n--队列为空,无法查找队头元素--\n");return ERROR;} //队列空
e = (*Q).base[(*Q).front];
printf("\n--队头元素为:%d--\n",e);
return OK;
}
int EnQueue(SqQueue *Q,int e)
{
int del;
printf("\n*****插入队尾元素*****\n");
while(((*Q).rear+1)%MAXSIZE == (*Q).front) //队满后队头出队,新数据插入到队尾
{
printf("\n--队列已满,队头出队--\n");
del = (*Q).base[(*Q).front];
(*Q).front = ((*Q).front+1) % MAXSIZE;
printf("\n--已将队头元素:%d出队--\n",del);
}
//printf("\n--队头位置:%d--\n",(*Q).front);
//printf("\n--队尾位置:%d--\n",(*Q).rear);
printf("\n--插入的数据为:%d--\n",e);
(*Q).base[(*Q).rear] = e;
(*Q).rear =((*Q).rear+1) % MAXSIZE;
return OK;
}
int DeQueue(SqQueue *Q,int e)
{
printf("\n*****删除队头元素*****\n");
if((*Q).front == (*Q).rear) {printf("\n--队列为空,无法删除--\n");return ERROR;}
e = (*Q).base[(*Q).front];
(*Q).front = ((*Q).front+1) % MAXSIZE;
printf("\n--已将队头元素:%d删除--\n",e);
return OK;
}
int QueueTraverse(SqQueue *Q)
{
int i = (*Q).front;
if((*Q).base == NULL) {printf("\n--队列不存在,无法输出数据--\n");return ERROR;}
else if((*Q).front == (*Q).rear && (*Q).base != NULL) {printf("\n--队列为空,无法输出数据--\n");return ERROR;}
printf("\n队列如下:\n");
printf("-------------------------------------------------\n");
printf("数据 | ");
while(i != (*Q).rear)
{
printf("%d ",((*Q).base[i]));
i = (i+1) % MAXSIZE;
}
printf("\n");
return OK;
}
#include "M.h"
int main()
{
int i,e;
SqQueue myQ;
SqQueue *Q = &myQ;
//创建队列
InitQueue(Q);
QueueEmpty(Q);//判空
//录入数据
creatQueue(Q);
QueueLength(Q);
QueueTraverse(Q);
//查找对头元素
GetHead(Q,e);
//插入队尾元素
printf("\n请输入你要插入的数值:\n");
scanf("%d",&e);
while(e != 0)
{
EnQueue(Q,e);
QueueLength(Q);
QueueTraverse(Q);
printf("\n请输入你要插入的数值:\n");
scanf("%d",&e);
}
//删除队头元素
DeQueue(Q,e);
QueueTraverse(Q);
//清空队列
ClearQueue(Q);
QueueEmpty(Q);
QueueTraverse(Q);
//销毁队列
DestroyQueue(Q);
QueueTraverse(Q);
}