棧、隊列
阿新 • • 發佈:2019-03-08
特殊 輸入數據 浪費 單鏈表 () empty 循環 連接 class
棧和隊列也都是線性表,是操作受限的特殊線性表
棧 :先進後出
順序棧:假設有一個足夠大的存儲空間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; }
棧、隊列