数据结构——栈和队列

栈和队列是特殊的线性表,其特殊之处是他们的基本操作只是线性表操作的一个子集。下面分别介绍这两种数据结构。


1. 栈(Stack)


栈(Stack)是只能在表尾进行插入或删除的线性表,是后进先出(LIFO)的线性表。

跟线性表相似,他的存储结构也包括顺序和链式两种。

顺序栈的定义及初始化如下:

//顺序栈
#define INIT_SIZE 100
#define INCREMENT 10

typedef struct {
	ElemType *base; //栈底指针
	ElemType *top;  //栈顶指针
	int stacksize;	//目前已分配的空间
}SqStack;

int InitStack(SqStack *s) {
	s.base = (ElemType *)malloc(INIT_SIZE * sizeof(ElemType));
	if(s.base == NULL) return -1;
	s.top = s.base;
	s.stacksize = INIT_SIZE;
	return 1;
}

当栈满时添加内存分配:

int isFull(SqStack *s){
	if(s.top - s.base == s.stacksize)
		s.base = (ElemType *) realloc (s, (s.stacksize+INCREMENT) * sizeof(ElemType));
	if(s.base == NULL) return -1;
	s.stacksize += INCREMENT;
	return 1;
}

插入时s.top+1, 删除时s.top-1。


栈的链式结构及基本操作如下:

/*
  对栈实现初始化(链式结构),插入栈顶元素,删除栈顶元素,遍历栈,清空栈等基本操作
  */
 #include <stdio.h>
 #include <malloc.h>
 #include <stdlib.h>
 
 #define true 1
 #define false 0
 
 
 typedef struct Node
 {
     int data;
     struct Node *pNext;
 }NODE, *PNODE;
 
 typedef struct Stack
 {
     PNODE pTop;
     PNODE pBottom;
 }STACK, *PSTACK;
 
 void init(PSTACK pS);
 void push(PSTACK pS, int val);
 void traverse(PSTACK pS);
 int pop(PSTACK pS , int *val);
 void clear(PSTACK pS);
 int empty(PSTACK pS);
 
 int main(void)
 {
     STACK S ;
     int val;
     int i;
     
     init(&S);
     
     push(&S,1);
     push(&S,2);
     push(&S,3);
     push(&S,4);
     push(&S,5);
     push(&S,6);
 
     traverse(&S);
     
     if(pop(&S ,&val))
     {
         printf("遍历成功,出栈元素为%d\n",val);
     }
     else
     {
         printf("出栈失败!\n");
     }
     traverse(&S);
 
     clear(&S);
     
     traverse(&S);
     
     return 0 ;
 }
 
 //栈的初始化
 void init(PSTACK pS)
 {
     pS -> pTop = (PNODE)malloc(sizeof(NODE));
     
     if(NULL == pS -> pTop)
     {
         printf("动态内存分配失败!");
         exit(-1);
     }
     else
     {
         pS -> pBottom = pS -> pTop;
         pS -> pTop -> pNext = NULL;
     }
     
     return ;
 }
 
 //插入元素到栈顶
 void push(PSTACK pS , int val)
 {
     PNODE pNew = (PNODE)malloc(sizeof(NODE));
     
     pNew -> data = val;
     pNew -> pNext = pS -> pTop;
     pS -> pTop = pNew;
     
     return ;
 }
 
 //遍历栈S
 void traverse(PSTACK pS)
 {
     PNODE p = pS -> pTop;
     
     printf("栈内元素为:");
     while(p != pS -> pBottom)
     {
         printf("%d\t", p -> data);
         p = p -> pNext;
     }
     
     printf("\n");
     return ;
 }
 
 //判断栈是否为空
 int empty(PSTACK pS)
 {
     if(pS -> pTop == pS -> pBottom)
     {
         return true;
     }
     else
         return false;
 }
 
 //删除栈顶元素并将其值赋给*val
 int pop(PSTACK pS , int *val)
 {
     if(empty(pS))
     {
         return false;
     }
     else
     {
         PNODE r = pS -> pTop;
         *val = r -> data;
         pS -> pTop = r -> pNext;
         free(r);
         r = NULL;
     }
 }
 
 //清空栈S
 void clear(PSTACK pS)
 {
     if(empty(pS))
     {
         return;
     }
     else
     {
         PNODE p = pS -> pTop;
         PNODE q = NULL;
         
         while(p != pS -> pBottom)
         {
             q = p -> pNext;
             free(p);
             p = q ;
         }
         
         pS -> pTop = pS -> pBottom;
         
         return;
     }
 }

2 队列


队列(Queue)是在一段插入而在另一端删除的线性表,其数据元素满足先进先出(FIFO)的操作。

队列也包括链式和顺序结构,队列长度确定的情况下用顺序结构来表示。

用顺序结构表示队列时,由于插入和删除操作分别在不同端进行,因而可能出现插入端已位于预分配内存的末端,而实际内存中还有较多空间未使用。此时通过增加内存的方式来继续添加数据的方式会造成内存的浪费,故采用循环队列的方式来操作比较好。

循环队列的定义和基本操作如下:

/*
 循环队列的基本操作,初始化,入队,遍历,出队等操作
 */
 #include <stdio.h>
 #include <malloc.h>
 
 #define true 1
 #define false 0
 
 typedef struct Queue
 {
     int *pBase;     //定义数组pBase
     int front;
     int rear;
 }QUEUE;
 
 void init(QUEUE *pQ);
 int en_queue(QUEUE *pQ , int val);
 void traverse_queue(QUEUE *pQ);
 int out_queue(QUEUE *pQ , int *pVal);
 
 //循环队列的初始化
 void init(QUEUE *pQ)
 {
     pQ -> pBase = (int *)malloc(sizeof(int)*6);   //分配内存,数组长度为6
 
     pQ -> front = 0;                              
     pQ -> rear = 0;
 
     return;
 }
 
 //判断循环队列是否为满
 int full_queue(QUEUE *pQ)
 {
     if((pQ -> rear + 1) % 6 == pQ -> front)     
     {
         return true;
     }
     else
         return false;
 }
 
 //入队操作
 int en_queue(QUEUE *pQ , int val)
 {
     if(full_queue(pQ))
     {
         return false;
     }
     else
     {
         pQ -> pBase[pQ -> rear] = val;
         pQ -> rear = (pQ -> rear + 1) % 6;
 
         return true;
     }
 }
 
 
 //遍历循环队列
 void traverse_queue(QUEUE *pQ)
 {
     int i = pQ -> front;
 
     printf("遍历队列:");
     while(i != pQ -> rear)
     {
         printf("%d\t", pQ -> pBase[i]);
 
         i = (i + 1) % 6 ;
     }
 
     printf("\n");
 
     return;
 }
 
 //判断循环队列是否为空
 int empty_queue(QUEUE *pQ)
 {
     if(pQ -> front == pQ -> rear)
     {
         return true;
     }
     else
         return false;
 }
 
 //循环队列的出队操作
 int out_queue(QUEUE *pQ , int *pVal)
 {
     if(empty_queue(pQ))
     {
         return false;
     }
     else
     {
         *pVal = pQ -> pBase[pQ -> front];
         pQ -> front = (pQ -> front + 1) % 6;
 
         return true;
     }
 }




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值