间隔了好久,开始继续复习。
栈和队列是在程序中最常被用到的数据结构,其重要性不言而喻。
栈:
定义:限定仅在表尾进行插入和删除操作的线性表,因此表尾称之为栈顶,表头为栈底,重要特点是后进先出(LIFO)
操作:
- InitStack(&S) 初始化一个栈
- DestoryStack(&S)销毁一个已经存在的栈
- ClearStack(&S)清空一个栈
- StackEmpty(S)判断已存在的栈是否为空
- StackLength(S)求栈长度
- GetTop(S,&e)获取栈顶部元素
- Push(&S,e)将一个元素e压入栈(核心)
- Pop(&S,&e) 将栈顶元素出栈,并用e返回其值(核心)
实现(C语言):
和线性表的实现类似,栈也有两种实现方式,分别为顺序栈和链栈
顺序栈的实现:
/*栈和队列的实现(C语言版)-------顺序栈*/
#include<stdio.h>
#include<malloc.h>
#include"string.h"
#define STACK_INIT_SIZE 100//栈的基础容量
#define STACK_INCREMENT 100//栈增长量
#define overflow_error 0
#define OK 1
#define operate_error 2
#define stack_null_error 3
typedef struct{
int *top;
int *base;
int stackSize;
}SqStack;
/*
初始化顺序栈
*/
int InitStack(SqStack *S){
(*S).base = (int *)malloc(STACK_INIT_SIZE * sizeof(int));
if( (!(*S).base) ){
exit(overflow_error);
}
(*S).top = (*S).base;
(*S).stackSize = STACK_INIT_SIZE;
return OK;
}
/*
入栈操作,elem为要入栈的元素
*/
int PushStack(SqStack *S,int elem){
//如果内存不够用,则重新申请空间
if((*S).top-(*S).base>(*S).stackSize){
(*S).base = (int *)realloc((*S).base,((*S).stackSize+STACK_INCREMENT)*sizeof(int));
//未申请上空间
if(!(*S).base){
exit(overflow_error);
}
(*S).top = (*S).base+(*S).stackSize;
(*S).stackSize += STACK_INCREMENT;
}
*((*S).top)++ = elem;
return OK;
}
/*出栈操作,将栈顶元素出栈,并用elem将该元素返回*/
int PopStack(SqStack *S,int *elem){
//判断是否栈空
if((*S).top == (*S).base){
return stack_null_error;
}
*elem = *--((*S).top);//将元素弹出栈,并将指针下移
return OK;
}
/*获取栈顶元素,但是并不是将元素出栈,并用elem返回元素值*/
int GetTop(SqStack S,int *elem){
if(S.top == S.base){
return stack_null_error;
}
*elem = *(S.top-1);
return OK;
}
/*判断是否栈空*/
int StackEmpty(SqStack s){
int flag = 0;
if(s.base == s.top){
flag = 0;
}else{
flag = 1;
}
return flag;
}
/*根据操作返回的结果进行成功与否的显示*/
void Utils_Print_Msg(int flag){
if(flag == OK){
printf("成功\n");
}else{
printf("不成功\n");
}
}
/*主函数*/
int main(){
SqStack stack;
//栈初始化
int flag = InitStack(&stack);
Utils_Print_Msg(flag);
//入栈
flag = operate_error;
flag = PushStack(&stack,60);
flag = PushStack(&stack,50);
flag = PushStack(&stack,40);
flag = PushStack(&stack,30);
flag = PushStack(&stack,20);
Utils_Print_Msg(flag);
int getElem = 0;
GetTop(stack,&getElem);
printf("获取到的栈顶元素是%d\n",getElem);
//出栈
int elem = 0;
flag = operate_error;
flag = PopStack(&stack,&elem);
if(flag == OK){
printf("%d出栈成功\n",elem);
}else{
printf("%d出栈失败\n",elem);
}
//获取栈顶元素
GetTop(stack,&getElem);
printf("获取到的栈顶元素是%d\n",getElem);
return 0;
}
应用:
栈的应用十分广泛,所以也产生了许多使用栈的经典应用算法,几个简单的用用的简单实现。
数制转换:
/*
进制转换---除K取余法
int Num_10 十进制下的数
int Num_convered 要转换的的进制
*/
int Conversion(int Num_10,int Num_convered){
SqStack s;
InitStack(&s);
printf("数制转换前%d\n",Num_10);
while(Num_10){
PushStack( &s,(Num_10%Num_convered) );
Num_10 = Num_10/Num_convered;
}
printf("转换数制后");
while(StackEmpty(s)){
int e;
PopStack(&s,&e);
printf("%d",e);
}
printf("\n");
}
--------------------------------------
//在主函数中添加代码测试一下:
int num_10,num_convered;
printf("输入十进制数");
scanf("%d",&num_10);
printf("输入要转换的进制");
scanf("%d",&num_convered);
Conversion(num_10,num_convered);
队列:
定义:
队列是一种先进先出的数据结构,只允许在表的一端进行插入,在表的另一端进行删除元素。允许插入的一端叫队尾,允许删除的一端叫队头。
操作:
- InitQueue(&Q)初始化队列
- DestoryQueue(&Q)销毁队列
- ClearQueue(&Q)清空队列
- QueueEmpty(Q)队列为空
- GetHead(Q,&e)获得队首元素,并用e返回其值,但是并不出队
- EnterQueue(&Q,e)将元素e入队
- DeleteQueue(&Q,&e)将元素出队,并用e返回其值
实现(C语言版):
和之前的数据结构类似,队列也有两种实现方式,为顺序队列和链队列
单链队列的实现(C语言版):
/*栈和队列的实现(C语言版)-------单链队列*/
#include<stdio.h>
#include<malloc.h>
#define overflow_error 0
#define OK 1
#define operate_error 2
#define queue_null_error 3
/*队列的数据节点*/
typedef struct QNode{
int data;
struct QNode *next;
}QNode,*QueuePtr;
/*对头队尾指针*/
typedef struct {
QueuePtr front;
QueuePtr rear;
}LinkQueue;
/*初始化一个单链表队列*/
int InitQueue(LinkQueue *Q){
(*Q).front = (*Q).rear = (QueuePtr)malloc(sizeof(QNode));
if(!(*Q).front){
exit(overflow_error);
}
(*Q).front->next = NULL;
return OK;
}
/*将元素elem入队*/
int EnterQueue(LinkQueue *Q,int elem){
QueuePtr newNode = (QueuePtr)malloc(sizeof(QNode));
if(!newNode){
exit(overflow_error);
}
newNode->data = elem;
newNode->next = NULL;
(*Q).rear->next = newNode;
(*Q).rear = newNode;
return OK;
}
/*将队尾的元素出队,并用elem将其值返回*/
int DeleteQueue(LinkQueue *Q,int *elem){
if((*Q).front == (*Q).rear){
return queue_null_error;
}
QueuePtr deleteNode = (*Q).front->next;
*elem = deleteNode->data;
(*Q).front->next = deleteNode->next;
if((*Q).rear == deleteNode){
(*Q).rear = (*Q).front;
}
free(deleteNode);
return OK;
}
/*根据操作返回的结果进行成功与否的显示*/
void Utils_Print_Msg(int flag){
if(flag == OK){
printf("成功\n");
}else{
printf("不成功\n");
}
}
/*主函数*/
int main(){
LinkQueue queue;
//初始化队列
int flag = operate_error;
flag = InitQueue(&queue);
Utils_Print_Msg(flag);
//将元素elem插入队尾
flag = operate_error;
flag = EnterQueue(&queue,78);
flag = EnterQueue(&queue,567);
flag = EnterQueue(&queue,21);
flag = EnterQueue(&queue,26);
flag = EnterQueue(&queue,54);
flag = EnterQueue(&queue,34);
flag = EnterQueue(&queue,8);
flag = EnterQueue(&queue,37);
Utils_Print_Msg(flag);
//将队头元素出队,并用elem将其值返回
flag = operate_error;
int deleteNum;
flag = DeleteQueue(&queue,&deleteNum);
if(flag){
printf("%d\n",deleteNum);
}else{
printf("失败");
}
flag = DeleteQueue(&queue,&deleteNum);
if(flag){
printf("%d\n",deleteNum);
}else{
printf("失败");
}
flag = DeleteQueue(&queue,&deleteNum);
if(flag){
printf("%d\n",deleteNum);
}else{
printf("失败");
}
flag = DeleteQueue(&queue,&deleteNum);
if(flag){
printf("%d\n",deleteNum);
}else{
printf("失败");
}
flag = DeleteQueue(&queue,&deleteNum);
if(flag){
printf("%d\n",deleteNum);
}else{
printf("失败");
}
return 0;
}