目录
一、栈
1、栈的定义及特点
受特殊限制的线性表,先进后出,后进先出
表尾端称为栈顶,表头端称为栈底,不含元素的空表称为空栈
栈的操作只在线性表表尾进行
top指向栈顶元素的后一位置
2、顺序栈
1、顺序栈的存储结构
#define MAXSIZE 100 //顺序栈存储空间
typedef struct
{
ElemType *base; //栈底指针
ElemType *top; //栈顶指针
int stacksize; //栈当前可用的最大容量
}SqStack;
2、创建一个空顺序栈
Status InitStack( SqStack &S)
{
S.base=(ElemType*)malloc(MAXSIZE*sizeof(ElemType));
//S.base=new ElemType[MAXSIZE];
if(!S.base) exit(OVERFLOW);
S.top = S.base; //一开始栈顶就是栈底
S.stacksize = MAXSIZE;
return OK;
}
3、顺序栈入栈

#define add 10 //追加空间
Status Push( SqStack &S, ElemType e)
{
//如果栈满,追加空间
if( S.top-S.base >= S.stacksize)
{
S.base=(ElemType*)realloc(S.base,(s.stacksize + add)*sizeof(ElemType));
if(!S.base) exit(OVERFLOW);
S.top = S.base + S.stacksize;
S.stacksize += add;
}
*(S.top ++) = e; //元素入栈,栈顶指针加一
}
4、顺序栈出栈 
Status Pop( SqStack &S,ElemType &e)
{
if(S.top == S.base) return ERROR; //空栈
e =*(--S.top); //栈顶指针减一,将栈顶元素赋值给e
return OK;
}
5、顺序栈取栈顶元素
Status GetTop(SqStack S)
{
if(S.top != S.base)
return *(S.top-1); //返回栈顶元素,栈顶指针不变
}
6、清空一个顺序栈
清空栈不是把栈的存储空间销毁,而是把栈中元素作废
Status ClearStack(SqStack &S)
{
S.top = S.base;
}
7、销毁一个顺序栈
Status DestroyStack( SqStack &S )
{
int i,len;
len = S.stacksize;
for(i=0;i<len;i++)
{
free(S.base);
S.base++;
}
S.base = S.top = NULL; //不让变成野指针
S.stacksize = 0;
}
8、计算顺序栈中元素个数
Status Stacklen( SqStack S )
{
return (S.top - S.base); //这里系统自动除以sizeof,所以返回的是元素个数
}
9、实例分析——二进制转十进制
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//顺序栈定义
#define OK 1
#define ERROR 0
#define MAXSIZE 100 //顺序栈存储空间的初始分配量
typedef int Status;
typedef char ElemType;
typedef struct
{
ElemType *base; //栈底指针
ElemType *top; //栈顶指针
int stacksize; //栈当前可用的最大容量
}SqStack;
//创建空栈
Status InitStack(SqStack *S)
{
S->base=(ElemType*)malloc(MAXSIZE*sizeof(ElemType));
if (!S->base) exit(0);
S->top = S->base;
S->stacksize = MAXSIZE;
return OK;
}
//顺序栈的入栈
Status Push(SqStack *S, ElemType e)
{
// 插入元素e为新的栈顶元素
if (S->top - S->base == S->stacksize) return ERROR; //栈满
*(S->top ++) = e; //元素e压入栈顶,栈顶指针加1
return OK;
}
//顺序栈的出栈
Status Pop(SqStack *S, ElemType *e)
{
//删除S的栈顶元素,用e返回其值
if (S->base == S->top) return ERROR; //栈空
*e = *(--S->top); //栈顶指针减1,将栈顶元素赋给e
return OK;
}
//计算栈中元素个数
int Stacklen(SqStack S)
{
return (S.top - S.base);
}
int main()
{
SqStack s; //定义栈
ElemType c;
Status len,i,sum=0;
InitStack(&s);
printf("请输入二进制数,输入#符号表示结束!\n");
scanf("%c",&c);
while(c != '#')
{
Push(&s,c);
scanf("%c",&c);
}
getchar(); //接收空格
len = Stacklen(s);
for( i=0; i<len ;i++)
{
Pop(&s,&c);
sum+=(c-'0')*pow(2,i);
}
printf("转换的十进制数是:%d",sum);
return 0;
}
3、链栈

1、链栈的存储结构
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LStackNode, *LinkStack;
2、创建一个空链栈
void InitStack(LinkStack &Top)
{
Top = (LinkStack)malloc(sizeof(LStackNode));
if(!Top) return;
Top->next = NULL;
}
3、链栈入栈
void PushStack(LinkStack &Top, SElemType e)
{
LinkStack newbase = (LinkStack)malloc(sizeof(LStackNode));
if(!newbase)
{
printf("内存空间分配失败!\n");
return;
}
newbase->data = e;
newbase->next = Top->next;
Top->next = newbase;
return;
}
4、链栈出栈
void PopStack(LinkStack &Top, SElemType &e)
{
LinkStack p = Top->next;
if(!p)
{
printf("栈为空!\n");
return;
}
Top->next = p->next;
e = p->data;
free(p);
return;
}
5、链栈取栈顶元素
void GetTopStack(LinkStack &Top, SElemType &e)
{
LinkStack p = Top->next;
if(!p)
{
printf("栈为空!\n");
return;
}
e = p->data;
return;
}
6、 计算链栈元素个数
int LengthStack(LinkStack &Top)
{
int len=0;
LinkStack p=Top;
while(p->next!=NULL)
{
len++;
p=p->next;
}
return len;
}
7、销毁一个链栈
void FreeStack(LinkStack &Top)
{
LinkStack p=Top,q;
while(p->next!=NULL)
{
q = p;
p = p->next;
free(q);
}
printf("栈已销毁!\n");
return;
}
二、队列
1、队列的定义及特点
只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
先进先出,后进后出
![]()
2、循环队列(队列的顺序表示)

头指针head始终指向队列头元素,尾指针tail始终指向队尾元素的下一个位置
1、循环队列的存储结构
#define MAXSIZE 100 //最大队列长度
typedef struct
{
ElemType *base; //类似顺序表中的elem数组
int front; //头指针,指向队列头元素
int rear; //尾指针,指向队列尾元素的下一个位置
}SqQueue;
2、构造一个空循环队列
Status InitQueue( SqQueue &Q )
{
Q.base=(ElemType*)malloc(MAXSIZE*sizeof(ElemType));
if(!Q.base) exit(OVERFLOW);
Q.front = Q.rear = 0;
return OK;
}
3、求队列长度
对于循环队列,头尾指针的差值可能是负数,因此要加上MAXSIZE,再与MAXSIZE取余
int Queuelength( SqQueue Q )
{
return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;
}
4、循环队列入队
Status EnQueue( SqQueue &Q, ElemType e )
{
if((Q.rear + 1) % MAXSIZE == Q.front) return ERROR; //队满
Q.base[Q.rear] = e; //队尾加新元素
Q.rear = (Q.rear + 1)% MAXSIZE;
return OK;
}
5、循环队列出队
Status DeQueue( SqQueue &Q, ElemType &e)
{
if(Q.front = Q.rear) return ERROR; //队空
e = Q.base[Q.front]; //保存表头元素
Q.front = (Q.front+1) % MAXSIZE;
return OK;
}
6、循环队列取队头元素
Status GetHead( SqQueue Q)
{
if(Q.front != Q.rear) //队非空
return Q.base[Q.front]; //返回队头元素的值,队头指针不变
}
3、链队(队列的链式表示)

1、链队的存储结构
typedef struct QNode
{
ElemType data;
struct QNode *next;
} QNode,*QueuePtr;
typedef struct
{
QueuePtr front; //队头指针
QueuePtr rear; //队尾指针
}LinkQueue;
2、创建一个空链队
Status InitQueue( LinkQueue &Q )
{
Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
//Q.front = Q.rear = new QNode;
if(!Q.front) exit(OVERFLOW);
Q.front->next = NULL; //头指针置空
return OK;
}
3、链队的入队

Status EnQueue(LinkQueue &Q, ElemType e)
{
QueuePtr p=(QueuePtr)malloc(sizeof(QNode));
if(!p) exit(OVERFLOW);
p->data=e;
p->next=NULL;
Q.rear->next=p; //尾指针指向的尾结点连接新结点
Q.rear=p; //尾指针指向新结点
}
4、链队的出队

Status DeQueue(LinkQueue &Q, ElemType &e)
{
if(Q.front==Q.rear)//空队列
return ERROR;
QueuePtr p = Q.front->next; //p指向首元结点
e = p->data;
Q.front->next=p->next;
free(p);
if(p==Q.rear)//此时删除最后一个结点(尾结点)
Q.rear = Q.front;
return OK;
}
在链队出队操作时还要考虑当队列中最后一个元素被删后,队列尾指针也丢失了,
因此需对队尾指针重新赋值(指向头结点)
5、 取链队的队头元素
ElemType GetHead( LinkQueue Q )
{
if(Q.front != Q.rear) //队列非空
return Q.front->next->data;
}
6、链队实例——舞伴问题
6-1 舞伴问题 (8 分)
函数接口定义:
void DancePartner(DataType dancer[], int num) ;其中 dancer[]是存放男士和女士信息的数组,num是数组大小。
裁判测试程序样例:
#include<stdio.h> #include<stdlib.h> typedef struct { char name[20]; char sex; } DataType; struct Node { DataType data; struct Node* next; }; typedef struct Node *PNode; struct Queue { PNode f; PNode r; }; typedef struct Queue *LinkQueue; LinkQueue SetNullQueue_Link() { LinkQueue lqueue; lqueue = (LinkQueue)malloc(sizeof(struct Queue)); if (lqueue != NULL) { lqueue->f = NULL; lqueue->r = NULL; } else printf("Alloc failure! \n"); return lqueue; } int IsNullQueue_link(LinkQueue lqueue) { return (lqueue->f == NULL); } void EnQueue_link(LinkQueue lqueue, DataType x) { PNode p; p = (PNode)malloc(sizeof(struct Node)); if (p == NULL) printf("Alloc failure!"); else { p->data = x; p->next = NULL; if (lqueue->f == NULL) { lqueue->f = p; lqueue->r = p; } else { lqueue->r->next = p; lqueue->r = p; } } } void DeQueue_link(LinkQueue lqueue) { struct Node * p; if (lqueue->f == NULL) printf("It is empty queue!\n "); else { p = lqueue->f; lqueue->f = lqueue->f->next; free(p); } } DataType FrontQueue_link(LinkQueue lqueue) { if (lqueue->f == NULL) { printf("It is empty queue!\n"); } else return (lqueue->f->data); } void DancePartner(DataType dancer[], int num) { /* 请在这里填写答案 */ } int main() { DataType dancer[9]; for (int i = 0; i < 9; i++) scanf("%s %c", dancer[i].name, &dancer[i].sex); DancePartner(dancer, 9); return 0; }输入样例:
李敏浩 M 李钟硕 M 高欣雅 F 吴彦祖 M 王思聪 M 张甜源 F 张智霖 M 许丹丹 F 马小云 F输出样例:
高欣雅 李敏浩 张甜源 李钟硕 许丹丹 吴彦祖 马小云 王思聪 张智霖
男女各一队,然后按队列顺序出队配对,最后输出没有配对的名字
void DancePartner(DataType dancer[], int num)
{
LinkQueue fdancer = SetNullQueue_Link();
LinkQueue mdancer = SetNullQueue_Link();
for(int i=0;i<num;i++)
{
if(dancer[i].sex=='M') EnQueue_link(mdancer,dancer[i]);
else EnQueue_link(fdancer,dancer[i]);
}
for(int i=0;i<num/2;i++)
if(!IsNullQueue_link(fdancer)&&!IsNullQueue_link(mdancer))
{
printf("%s %s\n",FrontQueue_link(fdancer).name,FrontQueue_link(mdancer).name);
DeQueue_link(fdancer);
DeQueue_link(mdancer);
}
printf("\n");
if(!IsNullQueue_link(fdancer)) printf("%s\n",FrontQueue_link(fdancer).name);
if(!IsNullQueue_link(mdancer)) printf("%s\n",FrontQueue_link(mdancer).name);
}
4、栈与队列比较

5、课后习题
1、设循环队列的元素存放在一维数组Q[0..29](下标为0到29)中,队列非空时,front指示队头元素位置,rear指示队尾元素的后一个位置。如果队列中元素的个数为11,front的值为25,则rear的值是( B )
A.5
B.6
C.35
D.36
(Q.rear-Q.front+MAXSIZE)%MAXSIZE=队列长度
(x-25+30)%30 = 11 ,即x-25+30=11 ,则x=6.
2、将一个10×10对称矩阵M的上三角部分的元素mi,j(1≤i≤j≤10)按列优先存入C语言的一维数组N中,元素m7,2在N中下标是( C )
A.15
B.16
C.22
D.23

因为对称矩阵,所以m7,2跟m2,7一样,因为列优先,则第一列1个,第二列2个……第七列2个
1+2+3+4+5+6+2=23,由于数组从0开始,则位置应是22
3、对n阶对称矩阵压缩存储时,需要表长为( C )的顺序表
A.n/2
B.n*n/2
C.n(n+1)/2
D.n(n-1)/2
对称矩阵的存储只需要存储其上三角或下三角部分(含对角线),元素个数为n +(n-1)+ (n -2) +..*+ 1 =n(n+1)/2
本文详细介绍了栈和队列这两种基本数据结构。栈是一种后进先出(LIFO)的数据结构,顺序栈和链栈是其两种实现方式;队列则是一种先进先出(FIFO)的数据结构,包括循环队列和链队的实现。文中通过实例分析了二进制转十进制问题,并对比了栈和队列的特点。同时,提供了创建、插入、删除等操作的具体代码实现。


683

被折叠的 条评论
为什么被折叠?



