這個作業屬於哪個課程 | https://edu.cnblogs.com/campus/qdu/DS2020 |
---|---|
這個作業要求在哪里 | https://edu.cnblogs.com/campus/qdu/DS2020/homework/11296 |
這個作業的目標 | ①掌握棧的結構特性及其入棧,出棧操作②掌握隊列的結構特性及其入隊、出隊的操作,掌握循環隊列的特點及其操作 |
學號 | 2018204167 |
一、實驗目的
1、掌握棧的結構特性及其入棧,出棧操作;
2、掌握隊列的結構特性及其入隊、出隊的操作,掌握循環隊列的特點及其操作。
二、實驗預習
說明以下概念
1、順序棧:
由於棧是運算受限的線性表,因此線性表的存儲結構對棧也適用。棧的順序存儲結構簡稱為順序棧,它是運算受限的順序表。
類似於順序表的定義,順序棧也可用向量來實現。因為棧底位置是固定不變的,所以可以將棧底位置設置在向量兩端的任意一個端點;棧頂位置是隨着進棧和退棧操作而變化的,故需用一個整型量top來指示當前棧頂位置,通常稱top為棧頂指針。
2、鏈棧:
棧的鏈式存儲結構稱為鏈棧。它是運算受限的單鏈表,其插入和刪除操作僅限制在表頭位置上進行。由於只能在鏈表頭部進行操作,故鏈棧沒有必要像單鏈表那樣需要附加頭結點。棧頂指針就是鏈表的頭指針。
3、循環隊列:
循環隊列就是將隊列存儲空間的最后一個位置繞到第一個位置,形成邏輯上的環狀空間,供隊列循環使用。在循環隊列結構中,當存儲空間的最后一個位置已被使用而再要進入隊列運算時,只需要存儲空間的第一個位置空閑,便可將元素加入到第一個位置,即將存儲空間的第一個位置作為隊尾。
4、鏈隊
隊列的鏈式存儲結構簡稱為鏈隊列,它是限制僅在表頭刪除和表尾插入的單鏈表。
顯然僅有單鏈表的頭指針不便於在表尾做插入操作,為此再增加一個尾指針,指向鏈表上的最后一個結點。於是,一個鏈隊列由一個頭指針和一個尾指針唯一地確定。
三、實驗內容和要求
1、閱讀下面程序,將函數Push和函數Pop補充完整。要求輸入元素序列1 2 3 4 5 e,運行結果如下所示。
#include<stdio.h>
#include<malloc.h>
#define ERROR 0
#define OK 1
#define STACK_INT_SIZE 10 /*存儲空間初始分配量*/
#define STACKINCREMENT 5 /*存儲空間分配增量*/
typedef int ElemType; /*定義元素的類型*/
typedef struct{
ElemType *base;
ElemType *top;
int stacksize; /*當前已分配的存儲空間*/
}SqStack;
int InitStack(SqStack *S); /*構造空棧*/
int push(SqStack *S,ElemType e); /*入棧*/
int Pop(SqStack *S,ElemType *e); /*出棧*/
int CreateStack(SqStack *S); /*創建棧*/
void PrintStack(SqStack *S); /*出棧並輸出棧中元素*/
int InitStack(SqStack *S){
S->base=(ElemType *)malloc(STACK_INT_SIZE *sizeof(ElemType));
if(!S->base) return ERROR;
S->top=S->base;
S->stacksize=STACK_INT_SIZE;
return OK;
}/*InitStack*/
int Push(SqStack *S,ElemType e){
}/*Push*/
int Pop(SqStack *S,ElemType *e){
}/*Pop*/
int CreateStack(SqStack *S){
int e;
if(InitStack(S))
printf("Init Success!\n");
else{
printf("Init Fail!\n");
return ERROR;
}
printf("input data:(Terminated by inputing a character)\n");
while(scanf("%d",&e))
Push(S,e);
return OK;
}/*CreateStack*/
void PrintStack(SqStack *S){
ElemType e;
while(Pop(S,&e))
printf("%3d",e);
}/*Pop_and_Print*/
int main(){
SqStack ss;
printf("\n1-createStack\n");
CreateStack(&ss);
printf("\n2-Pop&Print\n");
PrintStack(&ss);
return 0;
}
算法分析:輸入元素序列1 2 3 4 5,為什么輸出序列為5 4 3 2 1?體現了棧的什么特性?
體現了棧是只允許在表的一端進行操作的線性表且具有先進后出的特征。因為當main函數調用PrintStack(&ss)時,程序轉到函數中,而在該函數體內,又調用了int Pop(SqStack *S,ElemType *e),此函數的功能是棧S的棧頂元素退棧並返回其值。所以輸入元素序列1 2 3 4 5,輸出序列為5 4 3 2 1。這體現了棧是只允許在表的一端進行操作的線性表且具有先進后出的特征
2、在第1題的程序中,編寫一個十進制轉換為二進制的數制轉換算法函數(要求利用棧來實現),並驗證其正確性。
實現代碼
ElemType n,h;
int m=0,k=0;
InitStack(S);
printf("Input element\n");
scanf("%d",&n);
while(n){
m++;
Push(S,n%2);
n=n/2;
}
while(k<m){
k++;
Pop(S,&h);
printf("%d",h);
}
}
int main(){
SqStack S;
conveshen(&S);
printf("\n");
return ERROR;
}
驗證
3、閱讀並運行程序,並分析程序功能。
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#define M 20
#define elemtype char
typedef struct
{
elemtype stack[M];
int top;
}
stacknode;
void init(stacknode *st);
void push(stacknode *st,elemtype x);
void pop(stacknode *st);
void init(stacknode *st)
{
st->top=0;
}
void push(stacknode *st,elemtype x)
{
if(st->top==M)
printf("the stack is overflow!\n");
else
{
st->top=st->top+1;
st->stack[st->top]=x;
}
}
void pop(stacknode *st)
{
if(st->top>0) st->top--;
else printf(“Stack is Empty!\n”);
}
int main()
{
char s[M];
int i;
stacknode *sp;
printf("create a empty stack!\n");
sp=malloc(sizeof(stacknode));
init(sp);
printf("input a expression:\n");
gets(s);
for(i=0;i<strlen(s);i++)
{
if(s[i]=='(')
push(sp,s[i]);
if(s[i]==')')
pop(sp);
}
if(sp->top==0)
printf("'('match')'!\n");
else
printf("'('not match')'!\n");
return 0;
}
輸入:2+((c-d)6-(f-7)a)/6
運行結果:
輸入:a-((c-d)*6-(s/3-x)/2
運行結果:
程序的基本功能:
判斷多項式的左右括號是否配對
以下為選做實驗:
4、設計算法,將一個表達式轉換為后綴表達式,並按照后綴表達式進行計算,得出表達式得結果。
實現代碼
//中綴表達式轉后綴
#include<iostream>
#include<string>
#include<stack>
using namespace std;
int prio(char op) { //給運算符優先級排序
int priority;
if (op == '*' || op == '/')
priority = 2;
if (op == '+' || op == '-')
priority = 1;
if (op == '(')
priority = 0;
return priority;
}
bool Trans(string &str,string &str1) { //引用傳遞
stack<char> s; //定義一個char類型的棧s
int i;
for (i = 0; i<str.size(); i++) {
if (str[i] >= '0' && str[i] <= '9') { //如果是數字,直接入棧
str1+=str[i];
}
else { //否則不是數字
if (s.empty()) //棧空則入站
s.push(str[i]);
else if (str[i] == '(') //左括號入棧
s.push(str[i]);
else if (str[i] == ')') { //如果是右括號,只要棧頂不是左括號,就彈出並輸出
while (s.top() != '(') {
str1+= s.top();
s.pop();
}
s.pop(); //彈出左括號,但不輸出
}
else {
while (prio(str[i]) <= prio(s.top())) { //棧頂優先級大於等於當前運算符,則輸出
str1+= s.top();
s.pop();
if (s.empty()) //棧為空,停止
break;
}
s.push(str[i]); //把當前運算符入棧
}
}
}
while (!s.empty()) { //最后,如果棧不空,則彈出所有元素並輸出
str1+= s.top();
s.pop();
}
return true;
}
int main() { //主程序
string infix;
string postfix;
cout << "請輸入中綴表達式:" << infix << endl;
cin >> infix;
Trans(infix,postfix);
cout << "后綴表達式為:" << postfix << endl;
return 1;
}
5、假設以帶頭結點的循環鏈表表示隊列,並且只設一個指針指向隊尾結點(不設隊頭指針),試編寫相應的置空隊列、入隊列、出隊列的算法。
實現代碼:
/* 數據結構算法題(假設以帶頭結點的循環鏈表表示隊列,
* 並且只設一個指針指向隊尾元素結點(注意不設頭指針)
* 試編寫相應的隊列初始化,入隊列和出隊列的算法!)
*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define OK 1
#define ERROR 0
typedef int QElemType;
typedef int Status;
typedef struct QNode
{
QElemType data;
struct QNode * rear;
struct QNode * next;
}QNode,*LinkQueue;
//鏈式隊列的初始化
Status InitLinkQueue(LinkQueue * L)
{
(*L)=(LinkQueue)malloc(sizeof(QNode));
if((*L)==NULL)
{
printf("內存分配失敗!\n");
return OK;
}
(*L)->rear=(*L);
return OK;
}
//鏈式隊列的建立
Status Create(LinkQueue * L,int n)
{
srand(time(0));
LinkQueue P;
for(int i=0;i<n;i++)
{
P=(LinkQueue)malloc(sizeof(QNode));
P->data=rand()%100+1;
(*L)->rear->next=P;
(*L)->rear=P;
}
P->next=(*L);
return OK;
}
//入隊操作
Status EnQueue(LinkQueue * L,QElemType e)
{
LinkQueue P;
P=(LinkQueue)malloc(sizeof(QNode));
P->data=e;
P->next=(*L);
(*L)->rear->next=P;
(*L)->rear=P;
return OK;
}
//出隊操作
Status DeQueue(LinkQueue * L,QElemType * e)
{
LinkQueue temp;
*e=(*L)->next->data;
temp=(*L)->next;
(*L)->next=(*L)->next->next;
delete(temp);
return OK;
}
//輸出
void Print(LinkQueue * L)
{
LinkQueue P;
P=(*L)->next;
printf("輸出元素:\n");
while(P!=(*L))
{
printf("%d ",P->data);
P=P->next;
}
printf("\n");
}
int main()
{
LinkQueue L;
int ElemNumber;
QElemType EnElem,DeElem;
InitLinkQueue(&L);
printf("請輸入元素個數:\n");
scanf("%d",&ElemNumber);
Create(&L,ElemNumber);
Print(&L);
printf("請輸入入隊元素:\n");
scanf("%d",&EnElem);
EnQueue(&L,EnElem);
Print(&L);
printf("出隊操作,並返回出隊元素:\n");
DeQueue(&L,&DeElem);
printf("出隊元素為:%d\n",DeElem);
Print(&L);
return 0;
}
四、實驗小結
更好的了解掌握了棧的結構特性及其入棧,出棧操作,隊列的結構特性及其入隊、出隊的操作,循環隊列的特點及其操作