栈、队列
栈和队列也都是线性表,是操作受限的特殊线性表
栈 :先进后出
顺序栈:假设有一个足够大的存储空间data,用于存储栈中的元素,将栈中的元素依次存储到数组中--顺序存储方式--顺序栈。其中设置一个整形变量top,指示栈顶,即栈顶元素的数组下标,也可用来计数元素个数 将数组 data和top作为顺序栈的数据成员。
#include <iostream> #define MAXLEN 100 typedef int elementType; //顺序栈存储定义 typedef struct sStack{ elementType data[MAXLEN];//定义一个足够大的数组 int top;//指示栈顶 }seqStack;//顺序栈定义 //栈初始化 void initialStack(seqStack &s){ s.top = -1; } //判断栈空 bool stackempty(seqStack &s) { if (s.top == -1) return true; return false; }//简写 return(s.top == -1); //判断栈满 bool stackfull(seqStack &s) { if (s.top == MAXLEN-1) return true; return false } //取栈顶元素 bool getTop(seqStack &s,elementType &x){ if(stackempty){ return false; } else{ x = s.data[s.top]; return true; } } //入栈 bool push(seqStack &s,elementType x){ if (stackfull) return false else{ s.top++;//增加栈顶 s.data[s.top] = x;//数据入栈 return true; } } //出栈 bool pop(seqStack &s, elementType &x){ if (stackempty){ return false } else{ x = s.data[s.top]; top--; return true; } }
顺序栈特点:所有运算的时间复杂度均为O(1);通常一次性申请空间,只能按最大空间需求分配,容易造成空间浪费(可以使用链式栈代替顺序栈)
链栈 采用链式存储结构实现的栈,可以用单链表结构来表示,结点结构同单链表 链栈可以带头结点,也可以不带头结点。不带头节点栈顶指针top指示首元素节点,带头结点,栈顶指针top->next指示首元素节点
typedef int elementType; //elementType 定义为整数类型 typedef struct lsNode { elementType data; //链栈结点数据域 struct lsNode *next; //链栈结点指针域 } node,*linkedStack; //使后面使用node *top 或 linkedStack top都行 //初始化栈 不带头结点 void initialStack(node *&top) { top=NULL;//将栈顶指针置空 } //判定栈空 bool stackEmpty(node* top) { if(top==NULL) return true; //栈空,返回true else return false; //栈不空,返回false } //取栈顶元素 bool getTop(node * top, elementType &x) { if(top==NULL) return false; //栈空,返回false else { x=top->data; //取栈顶元素,用参数x返回 return true; //取栈顶成功,返回true } } //入栈 void push(node *& top, elementType x) { node* s; s=new node; s->data=x; s->next=top; top=s; } //出栈 bool pop(node *& top, elementType &x) { node* u; if(top==NULL) return false; //栈空,返回false else { x=top->data; //取栈顶元素,由变量x返回 u=top; //栈顶指针保存到u top=top->next; //栈顶指针后移一个元素结点 delete u; //释放原栈顶结点 return true; //出栈成功,返回true } } void destroyStack(node *& top) { node *p,*u; p=top; while(p) { u=p; p=p->next; delete(u); } top=NULL; } //交互循环压入元素 void createLinkedStack(linkedStack &top) { elementType x; node *p; cout<<"请输入数据元素(整数,-9999退出):"<<endl; cout<<"x="; cin>>x; while(x!=-9999) //非结束符,循环入栈 { p=new node; p->data=x; p->next=top; top=p; cout<<"x="; cin>>x; } }
链式栈特点:使用连续或不连续的存储空间,各数据元素独立存储,依靠指针连接建立逻辑相邻关系,对每个数据元素单独申请结点空间,没有栈满溢出的情况,栈顶指针top唯一确定一个链式栈。
逆置单链表:
1、从原链表首元素节点依次取出放入新表即可 头插法
void reverse(linkedStack & l) { node *p,*s; p = l ->next; l->next = NULL; while(p) { s = p; p = p->next; //利用s中转 s->next = l->next; l->next = s } }
2、定义一个顺序栈,循环每个节点指针入栈,首元素节点指针在栈底,将栈内节点依次弹出按尾插法来重建链表。
void reverse(linkedStack & l){ SeqStack S; initialStack(S); node* p ; p = l->next; while(p){ S.push(p); p = p->next; } l->next = NULL; while(!stackEmpty(S)){ p = S.pop(); l->next = p; } l->next = NULL }
队列 也是线性表,插入和删除只能在一端进行。
普通队列随着删除、插入的进行容易造成假溢出
循环队列
#define MAXLEN 100 typedef int elementType; //根据函数接收参数的不同 引用传值还是指针传值 用.给变量赋值 -> 指针赋值 typedef struct squeue { elementType data[MAXLEN]; int front,rear; }seqQueue; void initial(seqQueue * Q) { Q->front = 0; Q->rear = 0; } bool isEmpty(seqQueue & Q) { if (Q.front == Q.rear) return true; return false; } bool isFull(seqQueue & Q) { if ((Q.rear+1)%MAXLEN == Q.front) return true; else return false; } bool getFront(seqQueue &Q,elementType &x) { if isEmpty(Q) return false; else: x = Q.data[[Q.front+1] %MAXLEN] } bool enQueue(seqQueue &Q , elementType x) { if (isFull(Q)) return false; else Q.rear = (Q.rear+1)%MAXLEN; Q.data[Q.rear] = x; return true; } bool outQueue(seqQueue &Q, elementType &x) { if (isEmpty(Q)) return false; else Q.front = (Q.front+1)%MAXLEN; x = Q.data[Q.front]; return true; }
队列的应用 杨辉三角
void yanghuiTriangle(int n) { seqQueue Q; initial(&Q) int s1,s2,x; cout << 1<<endl; enQueue(&Q ,1) for (int i = 2; i <= n; i++) { s1 = 0; for (int j = 1; j <= i-1; j++) { getFront(Q,s2); outQueue(&Q,x); cout << s1+s2 <<"\t"; enQueue(&Q, s1+s2); 每次保证队列中是上一行的元素 在遍历队列依次相加 得到下一行元素 s1 = s2; } cout << 1<<endl; enQueue(&Q,1); } }
链队列 节点结构和单链表相同,需要两个指针分别指向队头和队尾。
typedef int elementType; typedef struct Node { elementType data; struct Node *next; }node; typedef struct queue { node *front; node *rear; }linkedQueue; void initial(linkedQueue &Q){ Q.front = new node; Q.rear = Q.front; Q.front->next = NULL; } bool isempty(linkedQueue &Q){ if (Q.rear == Q.front) return true; else return false; } bool getFront(linkedQueue &Q,elementType &x) { if (isempty(Q)) { return false;/* code */ } x =( (Q.front)->next)->data; return true; } void enQueue(linkedQueue &Q,elementType x) { node* p = new node; p->data = x; p->next = NULL; Q.rear ->next = p; Q.rear = p; } bool outQueue(linkedQueue &Q,elementType &x) { if (isempty(Q)) { return false;/* code */ } node *p = new node; p = Q.front->next; x = p->data; Q.front->next = p->next; delete(p); if (Q.front->next == NULL )//只有一个节点时 Q.rear = Q.front; return true } void destory(linkedQueue &Q){ node *p,*u; p = Q.front; while(p){ u = p; p = p->next; delete(u); } Q.front = NULL; Q.rear =NULL; }