数据结构——栈和队列

来源:互联网 发布:c语言爱心的代码 编辑:程序博客网 时间:2024/05/22 07:49

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


1. 栈(Stack)


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

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

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

//顺序栈#define INIT_SIZE 100#define INCREMENT 10typedef 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;     } }