数据结构队和栈的学习

学习感悟:

1、学习的持之以恒说着简单,实则很难,就像笔者最近感冒大部分时间被浪费,好不容易建立习惯也全然忘记,实在是三天打鱼两天晒网。

2、学习应该及时复习,温故而知新,在回顾的过程中还会发现之前的错误。

3、刚开始的时候不要太追求精益求精,就算是依托答辩你只要做出来了,也是胜利,笔者现在就是这个状态,有点草草了事之嫌。

4、坚持下去就是成功。

5. 直面自己的不足和缺点,勇于改正,接纳自己好的或者坏的方面,我们要做的事是直面问题并解决问题而不是逃避问题。

6..对于指针的认识还是云里雾里,特别是数据结构的结构体也是不太明白。

内容:

1.栈的顺序存储实现

2.栈的链式存储实现(没有写,以后来补)

3.队列的顺序存储实现

4.队列的链式存储实现 带头结点 不带头结点(有的时候在计算机里面样子无所谓,只要在逻辑上面符合输出要求就行)

#pragma once
#include<stdio.h>
#include<string.h>
#include<stdbool.h>
#include<stdlib.h>
#define Maxsize 10 //定义栈中元素最大个数
//栈的结构体
struct Sq{
	int data[Maxsize];//建立一个静态数组
	int top;//栈顶指针因为这是一个数组可以直接用下表指示
};
typedef struct  Sq SqStack;

//初始化栈
void InitStack(SqStack &S) {//&在c语言不能作为实参 在c语言中这只能通过指针来访问实参地址改变实参数值
	S.top = -1;

}


//对栈进行判空
bool StackEmpty(SqStack S){
	if (S.top == -1)
		return true;
	else
		return false;
} 
//新元素入栈
bool Push(SqStack& S, int x) {
	if (S.top == Maxsize - 1)return false;//栈已经满了
	S.top = S.top + 1;//先将栈指针向上移动
	S.data[S.top] = x;//再将元素插入栈中
	return true;//插入成功
}
//出栈操作
bool Pop(SqStack&S, int& x) {
	if (S.top == -1)return false;//栈为空
	x = S.data[S.top--];//先取数出栈然后栈顶指针-1
	return true;
}
//共享栈
typedef struct {
	int data[Maxsize];
	int top0;
	int top1;
}ShStack;
//初始化共享栈
void InitShStack(ShStack &S) {//初始化栈顶指针
	S.top0 = 0;//指向低地址的指针
	S.top1 = Maxsize - 1;//指向高地址指针
}

//对栈进行判空
bool StackEmpty(ShStack S) {
	if (S.top0== 0&&S.top1==Maxsize-1)
		return true;
	else
		return false;
}
//新元素入栈选择要插入的栈e
bool Push(ShStack& S, int x,int e) {
	if (S.top0+1 ==S.top1 )return false;//栈已经满了

	if (e == 0) {
		S.data[S.top0++] = x;
        return true;//插入成功
	}//选择栈0先将元素插入栈中再将栈指针向上移动
	if (e == 1) {
		S.data[S.top1--] = x;//选择栈1先将元素插入栈中再将栈指针向下移动
		return true;//插入成功
	}
}
//链式存储的栈 使用头插法

typedef struct Node {
	int data;
	struct Node* next;
} Node;

typedef struct Stack {
	Node* top;            // 栈顶指针
} Stack;

// 初始化栈
void initStack(Stack* s) {
	s->top = NULL;
}
// 入栈
void push(Stack* s, int data) {
	Node* newNode = (Node*)malloc(sizeof(Node));
	newNode->data = data;
	newNode->next = s->top;
	s->top = newNode;
}
// 出栈
int pop(Stack* s) {
	if (s->top == NULL) {
		printf("Stack is empty!\n");
		return -1; // 或者其他错误值
	}
	Node* temp = s->top;
	int poppedData = temp->data;
	s->top = s->top->next;
	free(temp);
	return poppedData;
}









//方案1队列的顺序实现
typedef struct {//队列的结构体
	int data[Maxsize];
	int front, rear;//队头指针队尾指针
}SqQueue1;
//初始化队列
void InitQueue1(SqQueue1 Q) {//将队头指针和队尾指针都指向0
	Q.front = Q.rear = 0;
}
//队空判断
bool QueueEmpty1(SqQueue1&Q) {
	if (Q.front == Q.rear)return true;
	else
		return false;
}
//队满判断(取余循环%Maxsize)牺牲一个存储单元,保证了插入时不会将元素插入把留于判断的空格
bool QueueFull1(SqQueue1&S) {
	/*if (S.front % Maxsize ==( S.rear+1) % Maxsize)return true; 这是不需要的*/
	if(S.front==(S.rear+1)) return true;
	else
		return false;

}

//入队操作 逻辑上处理逻辑化
bool EnQueue1(SqQueue1& Q, int x) {
	if (QueueFull1(Q) == true)return false;
	Q.data[Q.rear] = x;
	Q.rear=(Q.rear+1)%Maxsize;//保证了一种循环取余运算让存储空间在逻辑上成为了循环解构
	return true;

}
//出队操作
bool DeQueue1(SqQueue1& S, int& x) {//删除对头元素,并输出该元素
	if (QueueEmpty1(S) == true)//对队列进行判空操作
		return false;
	x = S.data[S.front];
	S.front = (S.front + 1) % Maxsize;
	return true;
}
//统计队列中有多少元素 数论模运算
int CountQueue1(SqQueue1& S,int&e) {
	e = (S.rear + Maxsize - S.front) % Maxsize;
	return e;
}






//方案2不浪费任何一个空间的方案 靠size变量区分队满和队空
typedef struct {
	int data[Maxsize];
	int front, rear;
	int size;
}SqQueue2;
//初始化
void InitQueue2(SqQueue2& Q) {//将队头指针和队尾指针都指向0,将队列元素个数初始化为0
	Q.front = Q.rear = 0;
	Q.size = 0;
}
//队空判断
bool QueueEmpty2(SqQueue2& Q) {
	if (Q.front == Q.rear&&Q.size==0)return true;
	else
		return false;
}
// 队满判断
bool QueueFull2(SqQueue2&Q) {
if (Q.front == Q.rear&&Q.size==Maxsize) return true;
else
return false;

}
//入队操作
 bool EnQueue2(SqQueue2& Q, int x) {
if (QueueFull2(Q) == true)return false;
Q.data[Q.rear] = x;
Q.rear = (Q.rear + 1) % Maxsize;//保证了一种循环取余运算让存储空间在逻辑上成为了循环解构
Q.size++;
return true;

}
//出队操作
bool DeQueue(SqQueue2&Q, int& x) {//删除对头元素,并输出该元素
	if (QueueEmpty2(Q) == true)//对队列进行判空操作
		return false;
	x = Q.data[Q.front];
	Q.front = (Q.front + 1) % Maxsize;
	Q.size--;
	return true;
}


//方案3不浪费任何一个空间的方案 靠tag插入时tag=1  删除时tag=0
//只有删除操作才能队空,插入操作才能队满。
typedef struct {
	int data[Maxsize];
	int rear, front;
	int tag;
}SqQueue3;
//队列的链式存储 和单链表区别 因为没有尾指针
typedef struct LinkNode {//链式队列结点
	int data;
	struct LinkNode* next;
}LinkNode;
typedef struct {//链式队列结构体
	LinkNode* front, * rear;//队头指针和队尾指针
}LinkQueue;
//初始化一个队列(带头结点)
void InitQueue1(LinkQueue&Q) {
	Q.front = Q.rear = (LinkNode*)(malloc(sizeof(LinkNode)));//初始时front rear 都指向头指针
	Q.front->next = NULL;
}
//判断队列是否是空队列
bool IsEmpty(LinkQueue Q) {
	if (Q.front == Q.rear)return true;
	else return false;

}
//新元素入队(带头结点)
void EnQueue(LinkQueue& Q, int x) {
	LinkNode* s = (LinkNode*)(malloc(sizeof(LinkNode)));
	s->data = x;
	s->next = NULL;
	Q.rear->next = s;//新结点插入rear之后
	Q.rear = s;//修改表尾指针

}
//出队(带头结点)
bool DeQueue(LinkQueue& Q, int& x) {
	if (Q.front == Q.rear)
		return false;//队空
	LinkNode* p = Q.front->next;//一个指针p队头元素
	x = p->data;//获取队头元素
	Q.front->next = p->next;//将对头元素删除
	if (Q.rear == p)//最后一个结点出队
		Q.rear = Q.front;//修改rear指针
	free(p);//释放待删除结点空间
	return true;
}
//初始化一个队列(不带头结点)
void InitQueue2(LinkQueue& Q) {
	Q.front = Q.rear = (LinkNode*)(malloc(sizeof(LinkNode)));//初始时front rear 都指向头指针
	Q.front->next = NULL;
}
//新元素入队(不带头结点)
void EnQueue2(LinkQueue&Q,int x) {
	LinkNode* s = (LinkNode*)(malloc(sizeof(LinkNode)));
	s->data = x;
	s->data = NULL;
	if (Q.front == NULL) {//空列表中插入第一个元素,另类头结点
		Q.front = s;//修改队头队尾指针
		Q.rear = s;
	}
	else {
		Q.rear->next = s;//新结点插入rear结点之后
		Q.rear = s;//修改rear指针,确定新队尾
	}

}

本人文章错误较多,以后回看可能不免发笑,但是贵在真实记录我的学习认识和过程,单纯的摘抄和引用确实错误更少,但是人总是要勇于面对自己的弱点。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值