栈
栈的本质就是一个线性表,也分有顺序存储和链式存储(一般用到顺序存储结构)。
特点:先进后出,只能对队尾操作。
最开始栈中不含有任何数据,栈顶即栈底,也称作空栈。
栈顶是指有效地址之后的一个元素地址
顺序存储栈结构
定义一个栈结构:
typedef int Elemtype;
typedef struct
{
Elemtype *base; //指向栈底
Elemtype *top; //指向栈顶
int stackSize; //栈的最大容量
}sqStack;
初始化栈:
#define Init_SIZE 100;
InitStack(sqStack *s)
{
s->base = (Elemtype *)malloc(Init_SIZE*sizeof(Elemtype));
if(!s->base)
{exit(0)};
s->top = s->base; //栈顶就是栈底
s->stacksize = Init_SIZE;
}
压栈:
#define Increment 10
Push(sqstack *s,Elemtype e)
{
if(s->top - s->base > = s->stackSize)//栈已满
{
s->base = (Elemtype *)realloc(s->base,(s->stackSize + Increment)*sizeof(Elemtype));//扩栈
if(!s->base)
exit(0);
s->top = s->base + s->stackSize;//设置栈顶
s->stackSize = s->stackSize + Increment;
}
*(s->top) = e;
(s->top)++;
}
出栈:
Pop(sqstack *s,Elemtype *e)
{
if(s->base = s->top)//空栈
return;
(s->top)--; //*base=1,*(base+1) = 2,top指向 base+2
*e = *(s->top);
}
清空栈:
Clearstack(sqstack *s)
{
s->top=s->base;
}
//使得栈顶等于栈尾,并不清空物理空间(栈容量),直接清空栈列表中的元素。
销毁栈:
DestroyStack(sqstack *s)
{
int i,len;
len = s->stackSize;
for(i = 1;i < len ;i++){
free(s->base);
s->base++;
}
s->base = s->top = NULL;
s->stackSize = 0;
}
计算栈的当前容量:
int stacklen(sqstack s)
{
return(s->top - s->base);//指针允许相减(不能相加)
}
链式存储栈结构
typedef char Elemtype;
typedef struct StackNode
{
Elemtype data;//栈元素
struct StackNode *Next;//Next为前一栈
}StackList,*LinkStackPtr;
typedef struct LinkStack
{
LinkStackPtr top;//栈顶-指向最末的有元素栈
int count;
}
void InitStackList(LinkStack *s)
{
s->top = NULL;
s->count = 0;
}
void Push(LinkStack *s,Elemtype e)
{
p = (LinkStackPtr)malloc(sizeof(StackNode));
p->data = e;
p->next = s->top;
s->top = p;
(s->count)++;
}
void Pop(LinkStack *s,Elemtype *e)
{
LinkStackPtr p;
if (s->top == NULL)
{
return 1;
}
*e = s->top->data;
p = s->top;
s->top = s->top->next;
free(p);
(s->count)--;
}
队列
与栈结构相同,队列也是一种重要的线性结构。
实现一个队列,同样需要顺序表或者链表作为其基础。
重要特点:先进先出,只允许一端入列操作,另一端出列操作。栈一般我们用顺序表来实现,而队列我们常用链表来实现,简称为链队列。
链队列
定义一个链队列结构:
typedef struct QNode
{
Elemtype data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct
{
QueuePtr front,rear;//队头,队尾
}LinkQueue;
//空队列时,头尾都指向头结点
初始化:
InitQueue(LinkQueue *q)
{
q->front = q->rear =(QueuePtr)malloc(sizeof(QNode));
if(q->front == NULL)
{
return 1;
}
q->front->next = NULL;
}
//入列
InsertQueue(LinkQueue *q,Elemtype e)
{
QueuePtr temp = (QueuePtr)malloc(sizeof(QNode));
temp->data = e;
p->next = NULL;
q->rear->next = temp;
q->rear = temp;
}
//出列
DeleteQueue(LinkQueue *q,Elemtype *e)
{
QueuePtr temp;
if(q->front == q->rear)
{
return 1;//空队列
}
temp = q->front->next;
if(q->rear == temp)
{
q->rear = q->front;//只有一个结点的特殊情况
}
*e = temp->data;
q->front->next = temp->next;
free(temp);
}
//销毁
DestoryQueue(LinkQueue *q)
{
while(q->front){
q->rear = q->front->next;
free(q->front);
q->front = q->rear;
}
}
顺序存储队列
顺序存储结构:
假设有一个n个元素,那么必须创建一个大于n的顺序队列(数组最后一个空间是不用的),使用循环队列逻辑,解决效率(普通队列数组,加入时‘O(1)’,推出时则要’O(n)’)和“假溢出”的问题。
取模运算:商永远不会大于除数。
#define MaxSize 100
typedef struct
{
Elemtype *base;
int front;
int rear;
} * CycleQueue
InitQueue(CycleQueue *q)
{
q->base = (Elemtype *)malloc(Maxsize * sizeof(Elemtype));
if(q->base == NULL)
{
exit(1);
}
q->front = q->rear = 0;
}
InsertQueue(CycleQueue *q,Elemtype e)
{
if((q->rear +1)%MaxSize == q->front)
{return;}//队列已满,数组最后一个空间是不用的
q->base[q->rear] = e;
q->rear = (q->rear+1) % MaxSize;//取模运算,永远不大于被除数
}
DeleteQueue(CycleQueue *q,Elemtype *e)
{
if(q->front == q->rear)
{return;}//空队列
*e = q->base[q->front];
q->front = (q->front+1) % MaxSize;
}