数据结构第三章栈、队列和数组总结

//3.1.1
/*栈的基本操作
InitStack(&S);初始化栈
DestroyStack(&L);销毁栈
Push(&L,x);入栈
Pop(&L,&x);出栈
GetTop(S,&x);读取栈顶元素
StackEmpty(S);判空
*/
//3.12顺序栈
//定义
#define MaxSize 10
typedef sturct{
	ElemType data[MaxSize];
	int top;
}SqStack;

//初始化栈
void InitStack(SqStack& S) {
	S.top = -1;//也可以定义成S.top,此时进栈出栈需要更改操作顺序;
}
void testStack() {
	SqStack S;
	InitStack(S);
}

//判空
bool StackEmpty(SqStack S) {
	if (S.top == -1) {
		return true;
	else
		return false;
	}
}

//进栈
bool Push(SqStack& S, ElemType x) {
	if (S.top == MaxSize - 1)//栈满
		return false;
		S.top = S.top + 1;
	    S.data[S.top] = x;//=S.data[++S.top]=x;
		return true;
}

//出栈
bool Pop(SqStack &S, ElemType &x) {
	if (S.top == -1)//栈空
		return false;
		x = S.data[S.top--];//x=S.data[S.top],S.top--;
	return true;
}

//共享栈
#define MaxSize 10
typedef struct {
	ElemType data[MaxSize];
	int top0;
	int top1;
}ShStack;

//初始化栈
void InitStack(ShStack& S) {
	S.top0 = -1;
	S.top1 = MaxSize;
}
//栈满条件:top0 + 1 == top 1;

//3.1.3
//栈的链式存储
//定义
typedef struct StackNode {
	ElemType data;
	struct StackNode* next;//指针域
}StackNode,*LinkStack;

//链栈的初始化
bool InitStack(LinkStack &S)//不带头结点
{
	S = NULL;  //将栈顶指针置空
	return true;
}

//链栈进栈
bool Push(LinkStack& S, int e)
{
	//元素e入栈
	StackNode* p;f
	p = (StackNode*) malloc (sizeof(StackNode*); 
	p->data = e;        // 将新节点数据域置为e
	p->next = S;        // 将新节点插入栈顶
	S = p;              // 修改栈顶指针
	return true;        //链栈要注意指针的方向是从栈顶指向栈底的 
}

//链栈出栈
int Pop(LinkStack& S, int& e)
{
if (S == NULL)
{
	return true;    // 栈空
}
e = S->data;      //将栈顶元素赋值给e
StackNode* p;
p = S;              // 临时保存栈顶元素空间,准备释放
S = S->next;     // 修改栈顶指针
free(p);;     // 释放原栈顶元素空间
return true;
}

//取栈顶元素
int GetTop(LinkStack S)
{
	//返回S的栈顶元素,不修改栈顶指针
	if (S != NULL)  // 栈非空
		return s->data;  // 返回栈顶元素的值,栈顶指针不变
}

//遍历
void TraveStack(LinkStack S)
{
	StackNode* p;
	p = S;
	while (p)
	{
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
}

//测试main
int main()
{
	LinkStack S;
	if (InitStack(S))
	{
		printf("链栈初始化成功!\n");
	}
	else
	{
		printf("链栈初始化失败!\n");
	}
	// 入栈
	int n;
	printf("请输入栈的元素个数:");
	scanf("%d", &n);
	for (int i = 0; i < n;)
	{
		int e;
		printf("请输入第%d个入栈的元素:", ++i);
		scanf("%d", &e);
		Push(S, e);
	}
	printf("遍历栈:\n");
	TraveStack(S);
	// 出栈(取出两个元素)
	for (int i = 0; i < 2;)
	{
		int a;
		Pop(S, a);
		printf("第%d个出栈的元素:%d\n", ++i, a);
	}
	printf("遍历栈:\n");
	TraveStack(S);
	printf("栈顶元素是:%d\n", GetTop(S));
	system("pause");
	return 0;
}

//3.2_1队列的基本概念(先进先出)FIFO
/*
InitQueue(&Q);初始化队列
DestroyQueue(&Q);销毁队列
EnQueue(&Q,x);入队
DeQueue(&Q,&x);出队
GetHead(Q,&L);读对头元素
QueueEmpty(Q);判空
*/

//3.2_2
//队列的顺序实现
#define MaxSize 10
typedef struct {
	ElemType data[MaxSize];//静态数组,连续的存储空间
	int front, rear;
}SqQueue;

//初始化队列
void InitQueue(SqQueue& Q) {
	Q.rear = Q.front = 0;
}
void testQueue() {
	SqQueue Q;
	InitQueue(Q);
}//测试

//入队
bool EnQueue(SqQueue &Q, ElemType x){
	if (队列已满)
		return false;
	Q.data[Q.rear] = x;
	Q.rear = (Q.rear + 1) % MaxSize;
	return true;
}

//判空
bool QueueEmpty() {
	if (Q.rear == Q.front)
		return true;
	else
		return false;
}

//循环队列
//入队
bool EnQueue(SqQueue &Q, ElemType x) {
	if (Q.rear+1)%MaxSize ==Q.front)
		return false;
	Q.data[Q.rear] = x;
	Q.rear = (Q.rear + 1) % MaxSize;
	return true;
}

//判空
bool QueueEmpty() {
	if (Q.rear == Q.front)
		return true;
	else
		return false;
}

/*判满条件
	(Q.rear + 1) % MaxSize == Q.front;
*/

//出队
bool DeQueue(SqQueue& Q, ElemType& x) {
	if (Q.rear == Q.front)//判空条件
		return false;
	x = Q.data[Q.front];
	Q.front = (Q.front + 1) % MaxSize;
	return true;
}

//取得对头元素的值,并用x返回
bool GetHead(SqQueue& Q, ElemType& x) {
	if (Q.rear == Q.front)//判空条件
		return false;
	x = Q.data[Q.front];
	return true;
}
//在上述方法下,队列队头指针需要浪费一片存储空间,为了解决这个问题,如下:
#define MaxSize 10
typedef struct {
	ElemType data[MaxSize];//静态数组,连续的存储空间
	int front, rear;
	int size;
}SqQueue;
/*方案二:我们定义了一个size变量,初始化时 rear=front=0;size=0;
插入成功 size++; 删除成功 size--;
队满条件 size==MaxSize; 队空条件 size=0;
*/

typedef struct {
	ElemType data[MaxSize];//静态数组,连续的存储空间
	int front, rear;
	int tag;
}SqQueue;
/*方案三:我们定义了一个tag变量,初始化时 rear=front=0;size=0;
每次插入成功都令 tag=1; 每次删除成功都令 tag=0;
队满条件 front==rear&&tag=1; 队空条件 front==rear&&tag=0;
*/

/*若队尾指针指向队尾元素
入队操作Q.data[Q.rear] = x;
Q.rear = (Q.rear + 1) % MaxSize;
初始化时:front指向0这个位置,rear指针指向n-1这个位置;
队空:rear->next=front;
队满:在front和rear中间增加一个空间不存放数据,rear->next->next=front;
*/

//3.2_3
//队列的链式实现(一般不会满,除非内存不够)
typedef struct LinkNode {
	ElemType data;
	struct LinkNode* next;
}LinkNode;
typedef struct {
	LinkNode* front, * rear;
}LinkQueue;

//1.初始化(带头结点)
void InitQueue(LinkQueue& Q) {
	Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
	Q.front->next = NULL;//或者Q.rear->next=NULL;
}
void testLinkQueue() {
	LinkQueue Q;
	InitQueue(Q);
}
bool IsEmpty(LinkQueue Q) {//队空
	if (Q.front == Q.rear)//Q.front->next=NULL;
		return false;
	else
		return false;
}
//入队
void EnQueue(LinkQueue& Q, ElemType x) {
	LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
	s->data = x;
	s->next = NULL;
	Q.rear->next = s;
	Q.rear = s;
}
//出队
bool DeQueue(LinkQueue& Q, ElemType& x) {
	if (Q.front == Q.rear)
		return false;
	LinkNode* p = Q.front->next;
	x = p->data;
	Q.front->next = p->next;
	if (Q.rear == p)//此次是最后一个结点出队
		Q.rear = Q.front;
	free(p);
	return true;
}


//2.初始化(不带头结点)
void InitQueue(LinkQueue& Q) {
	Q.front = NULL;
	Q.rear = NULL;
}
bool IsEmpty(LinkQueue Q) {//队空
	if (Q.front == NULL)//Q.rear==NULL;
		return false;
	else
		return false;
}
//入队
void EnQueue(LinkQueue& Q, ElemType x) {
	LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
	s->data = x;
	s->next = NULL;
	if (Q.front == NULL) {//在空队列中插入第一个元素
		Q.front = s;
		Q.rear = s;
	}
	else {
		Q.rear->next = s;
		Q.rear = s;
	}
}
//出队
bool DeQueue(LinkQueue& Q, ElemType& x) {
	if (Q.front == NULL)
		return false;
	LinkNode* p = Q.front;
	x = p->data;
	Q.front = p->next;
	if (Q.rear == p) {//此次是最后一个结点出队
		Q.front = NULL;
		Q.rear = NULL;
	}
	free(p);
	return true;
}

//3.2_4双端队列

//3.3_1栈在括号匹配中的应用
#define MaxSize 10
typedef struct {
	char data[MaxSize];
	int top;
}SqStack;

void InitStack(SqStack& S);//初始化栈
bool StackEmpty(SqStack S);//判空
bool Push(SqStack& S, char x);//入栈
bool Pop(SqStack& S, char& x);//出栈,用 x返回

bool bracketCheck(char str[], int length) {
	SqStack S;
	InitStack(s);
	for (int i = 0; i < length; i++) {
		if (str[i] == '(' || str[i] == '[' || str[i] == '{') {
			Push(S, str[i]);
		}
		else {
			if (StackEmpty(S)) {//扫描到有括号,且当前栈空
				return false;
			}
			char topElem;
			Pop(S, topElem);
			if (str[i] == ')' && topElem != '(')
				return false;
			if (str[i] == ']' && topElem != '[')
				return false;
			if (str[i] == '}' && topElem != '{')
				return false;

		}
	}
	return StackEmpty(S);//检索完全部括号后,栈空说明匹配成功
}

//栈在表达式中的应用
/*1.中缀表达式转后缀表达式(左优先原则)
2.中缀表达式转前缀表达式(右优先原则)

此处较重要,具体看ppt


*/

//3.3_4
//栈在递归中的应用



//3.3_5队列的应用
//1.树的层次遍历 2.图的广度优先遍历 3.队列在操作系统中的应用

//特殊矩阵的压缩存储
/*1.一维数组,二维数组
* 2.普通矩阵的压缩
* 3.特殊矩阵(都是方阵)如下:(掌握一维二维数组位置的转换(注意矩阵或者数组下标是0还是1))
* 对称矩阵的压缩
* 三角矩阵的压缩
* 三对角矩阵的压缩(1.顺序存储-三元组 2.链式存储-十字链表法)
*/

你可能感兴趣的:(数据结构)