广州大学学生实验报告
开课学院及实验室: 计算机科学与工程实验室 418 202 2年10月3 日
学院 | 计算机科学与网络工程 | 年级、专业、班 | 计科 | 姓名 | Great Macro | 学号 | ||
实验课程名称 | 数据结构实验 | 成绩 | ||||||
实验项目名称 | 线性表、堆栈和队列的操作与实现 | 指导老师 |
- 实验目的
1. 掌握线性表、栈和队列的基本操作;
2. 实现线性表的查找、插入、删除等基本操作;
3. 实现链栈的初始化、入栈、出栈和取栈顶元素等基本操作;
4. 实现链式队列的初始化、入队、出队等基本操作。
- 使用仪器、器材
1. 微机一台
2. 操作系统:WINXP / win8 / win10
3. 编程软件:C / C++ / JAVA
- 实验内容及原理
//描述具体做什么,算法原理、做法
内容:
线性表是相同性质的元素构成的有穷序列,栈、队列则是操作限于两端的特殊的线性表。它们均涉及创建、插入、删除、获取长度、获取端点等约十种基本操作(参见《数据结构》教材第2、3章有关内容)。这里要求定义实现线性表、链式栈和队列,其中至少包括创建、相关的插入和删除等操作。
线性表:
// 创建、插入、删除、获取长度、获取端点等约十种基本操作 #include <iostream> using namespace std; // 定语单链表结构体 typedef struct LNode { int data; // 结点的数据域 LNode *next; // 结点的指针域 }LNode; // 生成一结点 LNode *initList(void) { LNode *p = new LNode; if(!p) { cout << "动态分配内存空间出错\n"; return NULL; } p->data = 0; p->next = NULL; return p; } // 头插法插入一个节点 void head_insert(LNode *head, LNode *p) { p->next = head->next; head->next = p; } // 头插法创建一个链表 bool creatList(LNode *head, int len) { // 判断表是否存在 if(!head) { cout << "创建链表失败\n"; return false; } for(int i = 0; i < len; i++) { LNode *p = initList(); if(!p) { cout << "创建链表失败\n"; return false; } cout << "请输入结点数据:"; cin >> p->data; head_insert(head, p); } return true; } // 计算链表的长度 int listLength(LNode *head) { // 判断表是否存在 if(!head) { return -1; } int i = 0; for(LNode *p = head->next; p; p = p->next, i++); return i; } // 判断是否为空表 int isEmpty(LNode *head) { // 判断表是否存在 if(!head) { return -1; } return !head->next; } // 头删法,将链表清空 bool clearList(LNode *head) { // 判断表是否存在 if(!head) { return false; } LNode *p; while(head->next) { p = head->next; // 弹出首元节点 head->next = p->next; // head->next指向下一个节点 delete p; } return true; } // 头删法,销毁链表 bool destroyList(LNode *head) { // 判断表是否存在 if(!head) { return false; } LNode *p; while(head->next) { p = head->next; // 弹出首元节点 head->next = p->next; // head->next指向下一个节点 delete p; } delete head; return true; } // 查找某个节点, 成功返回指向该节点的指针 LNode *findNode(LNode *head, int data) { // 判断表是否存在 if(!head) { return NULL; } LNode *p; for(p = head->next; p; p = p->next) { if(p->data == data) { return p; } } return NULL; } // 修改某个节点数据 bool modifyNode(LNode *head, int old_data, int new_data) { LNode *p = findNode(head, old_data); // 判断节点是否存在 if(!p) { return false; } p->data = new_data; return true; } // 遍历链表 bool traverseList(LNode *head) { // 判断表是否存在 if(!head) { return false; } for(LNode *p = head->next; p; p = p->next) { cout << p->data << " "; } cout << endl; return true; } // 删除某个节点 int delNode(LNode *head, int data) { // 判断表是否存在 if(!head) { return -1; } LNode *p, *tmp; for(p = head; p->next; p = p->next) { if(p->next->data == data) { tmp = p->next; // 临时保存要被删除的节点 p->next = tmp->next; // 修改指针 delete tmp; return 1; } } return 0; } int main() { cout << "下面开始模拟单链表的操作\n"; int i, len, data; LNode *head, *p; head = initList(); if(!head) { cout << "初始化头结点失败\n"; return -1; } while(1) { cout << "请选择你的操作,1.创建单链表 2.插入新节点 3.删除节点 "; cout << "4.遍历链表 5.查找节点 6.链表长度 7.修改节点 8.清空链表 9.销毁链表 10.退出\n"; cin >> i; switch(i) { case 1: if(!head) { head = initList(); } cout << "请输入链表的长度:"; cin >> len; if(creatList(head, len)) { cout << "创建成功\n"; } else { cout << "创建失败\n"; } break; case 2: cout << "请输入要插入的数据:"; p = initList(); if(!p) { cout << "分配节点空间失败\n"; } else { cin >> p->data; head_insert(head, p); cout << "插入成功\n"; } break; case 3: cout << "请输入要删除的数据:"; cin >> data; if(delNode(head, data) < 0) { cout << "删除失败\n"; } else { cout << "删除成功\n"; } break; case 4: if(traverseList(head)) { cout << "遍历成功\n"; } else { cout << "遍历失败\n"; } break; case 5: cout << "请输入要查找的数据:"; cin >> data; if(findNode(head, data)) { cout << "链表中存在该元素\n"; } else { cout << "查找失败\n"; } break; case 6: if(isEmpty(head) == -1) { cout << "链表不存在\n"; } len = listLength(head); if(len != -1) { cout << "链表长度:" << len << endl; } break; case 7: cout << "请输入要修改的节点的原数据和新数据:"; cin >> data >> len; if(modifyNode(head, data, len)) { cout << "修改成功\n"; } else { cout << "节点不存在或者链表为空\n"; } break; case 8: if(clearList(head)) { cout << "清空成功\n"; } else { cout << "链表不存在\n"; } break; case 9: if(destroyList(head)) { head = NULL; cout << "销毁成功\n"; } else { cout << "链表不存在\n"; } break; } if(i == 10) { cout << "你已退出!\n"; break; } } return 0; }
链表另外一种写法:
typedef struct LNode {//定义链表 int data;//结点的数据域 LNode *next;//结点的指针域 }LNode,*LinkList; bool InitList(LinkList &L) {//创建 L = new LNode;//生成新结点作为头结点 L->next = NULL; return true; } bool ListEmpty(LinkList L) {//判断是否为空表 if (!L->next)return true; else return false; } int ListLength(LinkList L) {//求链表长度 int i = 0;//计数器 LNode* p = L->next;//指针p指向首元结点 while (p) { i++; p = p->next;//p指向下一个结点 } return i; } bool ListInsert(LinkList &L, int i, int e) {//插入 if (i <= 0 || i > ListLength(L)+1)return false;//位置不合法 LNode *p = L; int j = 0; while (p && (j < i - 1)) { p = p->next;//查找第i-1个结点,p指向该结点 j++; } if (!p || j > i - 1)return false; LNode *s = new LNode;//生成新的结点 s->data = e; s->next = p->next; p->next = s; return true; } bool GetElem(LinkList L, int i, int &e) {//取值 if (ListEmpty(L)) return false; if (i<= 0|| i > ListLength(L)) return false; LNode *p = L->next; int j = 1; while (p&&j < i) { p = p->next; j++; } if (!p || j>i)return false; e = p->data; return true; } bool ListDelete(LinkList &L, int i) {//删除元素 if (ListEmpty(L))return false;//空表无法删除 if(i <= 0||i>ListLength(L))return false;//输入不合法 LNode *p = L; int j = 0; while (p->next&&j < i - 1) {//查找第i-1个结点,p指向该结点 p = p->next; j++; } if (!p->next || j>i - 1)return false; LNode *q = p->next; p->next = q->next; delete q;//释放删除结点的空间 return true; } bool LocateElem(LinkList L, int e) {//查找 if (ListEmpty(L))return false; LNode *p = L->next; while (p&&p->data != e)//顺链域往后查找 p = p->next; if (!p)return false; cout<<"该元素的地址"<<p << endl; return true; } void CreateList_H(LinkList &L, int n) {//前插法,逆序输入 L = new LNode; L->next = NULL; cout << "请逆序输入元素的值" << endl; for (int i = 0; i < n; i++) { LNode *p = new LNode;//生成新结点 cout << "请输入元素的值:"; cin >> p->data; p->next = L->next; L->next = p; } } void CreateList_R(LinkList &L, int n) {//后插法,正序输入 L = new LNode; L->next = NULL; LNode *r = L;//尾指针 cout << "请正序输入元素的值" << endl; for (int i = 0; i < n; i++) { LNode *p = new LNode;//生成新结点 cout << "请输入元素的值:"; cin >> p->data; p->next = NULL;//这里可以改成r->next = p;r = p;r->next=NULL; r->next = p; r = p; } } bool DestroyList(LinkList& L) {//销毁链表 while (L->next) { LNode* p = L->next; L->next = p->next; delete p;//释放链表结点的空间 } delete L;//释放链表的头结点空间 return true; }
顺序栈:
const int maxsize= 100; struct SqStack {//定义顺序栈 int *base;//栈底指针 int *top;//栈顶指针 int stackszie; }; bool InitStack(SqStack &S) {//初始化栈 S.base = new int[maxsize];//分配栈的空间 if (!S.base)exit(0); S.top = S.base; S.stackszie = maxsize; return true; } bool Push(SqStack &S, int e) {//进栈 if (S.top - S.base == S.stackszie)return false; *S.top++ = e; return true; } bool Pop(SqStack &S,int &e) {//出栈 if (S.top == S.base)return false; e = *--S.top; return true; } bool StackEmpty(SqStack S) {//判断栈是否为空 if (S.base == S.top)return true; return false; } int GetTop(SqStack S) {//取栈顶元素 if (S.top != S.base) return *(S.top - 1); return -1; } int StackLength(SqStack S) {//求栈长 int* p = S.base;//指针p指向栈底指针 int i = 0; while (p != S.top) { i++; p++; } return i; } bool ClearStack(SqStack& S) {//清空栈 S.top = S.base;//栈顶指针指向栈底指针 return true; } bool DestroyStack(SqStack &S) {//销毁栈 delete S.base;//释放栈的空间 return true; }
链栈
typedef struct StackNode {//定义链栈
int data;
StackNode *next;
}StackNode,*LinkStack;
bool InitStack(LinkStack &S) {//初始化链栈
S = NULL;
return true;
}
bool Push(LinkStack &S, int e) {//进栈
StackNode *q = new StackNode;
q->data = e;
q->next = S;//将新结点插入栈顶
S = q;
return true;
}
bool Pop(LinkStack &S,int &e) {//出栈
if (S == NULL)return false;
e = S->data;
StackNode *q = S;
S = S->next;//修改栈顶指针
delete q;//释放栈顶元素的空间
return true;
}
int GetTop(LinkStack S) {//取栈顶元素
if (S != NULL)return S->data;
else exit(0);
}
int StackLength(LinkStack S) {//求栈长
int i = 0;
StackNode* p = S;
while (p) {
p = p->next;
i++;
}
return i;
}
bool StackEmpty(LinkStack S) {//判断栈是否为空
if (!S)return true;
return false;
}
bool DestroyStack(LinkStack S) {//销毁栈
while (S->next) {
StackNode* p = S->next;
S->next = p->next;
delete p;//释放栈的元素的空间
}
delete S;//释放栈的空间
return true;
}
循环队列
const int maxsize=100; struct SQueue { int *base; int front; int rear; }; bool InitQueue(SQueue &Q) { Q.base = new int[maxsize];//分配空间 if (!Q.base)exit(0); Q.front = Q.rear=0; return true; } int QueueLength(SQueue Q) { return (Q.rear - Q.front + maxsize) % maxsize;//求模长度 } bool EnQueue(SQueue &Q, int e) { if ((Q.rear + 1) % maxsize == Q.front)return false; Q.base[Q.rear] = e; Q.rear = (Q.rear + 1) % maxsize; return true; } bool DeQueue(SQueue &Q, int &e) { if (Q.front == Q.rear)return false; e = Q.base[Q.front]; Q.front = (Q.front + 1) % maxsize; return true; } int GetHead(SQueue Q) { if (Q.front != Q.rear)return Q.base[Q.front]; return -1; } bool DestroyQueue(SQueue &Q) { if (!Q.base)return false; delete []Q.base;//释放队列的空间 return true; } bool ClearQueue(SQueue &Q) { Q.front = Q.rear=0; return true; } bool QueueEmpty(SQueue Q) { if (Q.front == Q.rear)return true; return false; } bool QueueFull(SQueue Q) { if ((Q.rear + 1) % maxsize == Q.front)return true; return false; } bool QueueExist(SQueue Q) { if (Q.base)return true;//判断队列是否存在 return false; }
链队
typedef struct QNode { int data; QNode *next; }QNode,*QueuePtr; struct LinkQueue { QueuePtr front; QueuePtr rear; }; bool InitQueue(LinkQueue &Q) { Q.front = Q.rear = new QNode;//生成新的结点 Q.front->next = NULL; return true; } bool EnQueue(LinkQueue &Q, int e) { QNode *p = new QNode;//生成新的结点 p->data = e; p->next = NULL; Q.rear->next = p;//插入p到队列 Q.rear = p;//修改尾指针 return true; } bool DeQueue(LinkQueue &Q, int &e) { if (Q.front == Q.rear)return false; QNode *p = Q.front->next; e = p->data; Q.front->next = p->next;//修改队头指针 if (Q.rear == p)Q.rear = Q.front; delete p; return true; } int GetHead(LinkQueue Q) { if (Q.front != Q.rear)return Q.front->next->data; else return -1; } int QueueLength(LinkQueue Q) { QueuePtr p = Q.front->next; int i = 0; while (p) { p = p->next; i++; } return i; } bool QueueEmpty(LinkQueue Q) { if (!Q.front->next)return true; else return false; } bool DestroyQueue(LinkQueue& Q) { while (Q.front->next) { QueuePtr q = Q.front->next; Q.front->next =q->next; delete q;//释放队列元素的空间 } Q.rear = Q.front; delete Q.front;//释放队头元素的空间 return true; }
- 实验过程原始数据记录
//代码及调试信息、截屏说明
void test(LinkList &L) { int i,e; int key = 0; char choice; cout << "请选择对链表的操作:" << endl; cout << "A.创建 B.查表 C.查找 D.取值 E.删除 F.销毁 G.插入 H.遍历 I.退出" << endl; cin >> choice; while (1) { if (choice == 'A') { cout << "请选择创建方式:a.头插法 b.尾插法 "; cin >> choice; switch (choice) { case 'a': key = 1; cout << "请输入创建的链表的长度 "; cin >> e; CreateList_H(L, e); cout << "创建成功!" << endl; break; case 'b': key = 1; cout << "请输入创建的链表的长度 "; cin >> e; CreateList_R(L, e); cout << "创建成功!" << endl; break; } } if (choice == 'I') {cout << "你已退出!" << endl; break;} if(!key&&choice!='F') { cout << "该链表不存在!请先创建一个链表!" << endl; } cout << "请选择对链表的操作:" << endl; cout << "A.创建 B.查表 C.查找 D.取值 E.删除 F.销毁 G.插入 H.遍历 I.退出" << endl; cin >> choice; if (choice < 'A' || choice>'I') { cout << "输入不合法!请重新输入:"; cin >> choice; } if(key) { switch (choice) { case 'B': if (ListEmpty(L))cout << "这是一个空表!" << endl; else cout << "该链表的长度是:" << ListLength(L) << endl; break; case 'C': if (ListEmpty(L))cout << "这是一个空表!" << endl; else { cout << "请输入想查找元素的值:"; cin >> e; if (LocateElem(L, e))cout << endl; else cout << "链表中不存在该元素!" << endl; } break; case 'D': if (ListEmpty(L))cout << "这是一个空表!" << endl; else { cout << "请输入取值元素的序号:"; cin >> i; if (GetElem(L, i, e))cout << e << '\t' << "取值成功!" << endl; else cout << "链表中不存在该序号!该链表最大序号为:" << ListLength(L) << endl; } break; case 'E': if (ListEmpty(L))cout << "这是一个空表!" << endl; else { cout << "请输入删除的元素序号:"; cin >> i; if (ListDelete(L, i))cout << "删除成功!" << endl; } break; case 'F': if (DestroyList(L)) { key = 0; cout << "销毁成功!" << endl; } break; case 'G': cout << "请输入想插入的位置序号和元素:"; cin >> i >> e; if (ListInsert(L, i, e))cout << "插入成功!" << endl; else cout << "插入位置序号不合法!当前链表最大插入位置序号为:" << ListLength(L) + 1 << endl; break; case 'H': if (ListEmpty(L)) { cout << "这是一个空表!" << endl; } else { for (i = 1; i <= ListLength(L); i++) { GetElem(L, i, e); cout << e << " "; } cout << "遍历成功!" << endl; } break; } } } }
栈
顺序栈的测试函数:
void test(SqStack &S) { int i, e,k; int key = 0; char choice; cout << "请输入对顺序栈的操作:" << endl; cout << "A.初始化 B.进栈 C.出栈 D.取顶 E.查栈 F.清空 G.销毁 H.退出" << endl; cin >> choice; while (1) { if (choice == 'A') { InitStack(S); key = 1; cout <<"初始化成功!"<<endl; } if (choice == 'H') { cout << "你已退出!" << endl; break; } if (!key&&choice!='G') { cout << "栈不存在!请先初始化!" << endl; } cout << "请输入对顺序栈的操作:" << endl; cout << "A.初始化 B.进栈 C.出栈 D.取顶 E.查栈 F.清空 G.销毁 H.退出" << endl; cin >> choice; if (choice < 'A' || choice>'H') { cout << "输入不合法!请重新输入:"; cin >> choice; } if (key) { switch (choice) { case 'B': cout << "请输入进栈的元素的个数:"; cin >> i; for (int j = 0; j < i; j++) { cout << "请输入进栈的元素:"; cin >> e; Push(S, e); } cout << "进栈成功!" << endl; break; case 'C': if (StackEmpty(S)) cout << "这是一个空栈!" << endl; else { cout << "请输入出栈的元素的个数:"; cin >> i; if (i > StackLength(S)) { k = StackLength(S); cout << "当前栈最多能出栈" << StackLength(S) << "个元素!" << endl; } else k = i; for (int j = 0; j < k; j++) { Pop(S, e); cout << e << " "; } cout << endl << "出栈成功!" << endl; } break; case 'D': if (StackEmpty(S)) cout << "这是一个空栈!" << endl; else cout << GetTop(S) << " 取顶成功!" << endl; break; case 'E': if (StackEmpty(S)) cout << "这是一个空栈!" << endl; else cout << "当前栈的长度是:" << StackLength(S) << endl; break; case 'F':ClearStack(S); cout << "清空成功!" << endl; break; case 'G': key = 0; DestroyStack(S); cout << "销毁成功!" << endl; break; } } } }
链栈测试函数:
void test(LinkStack &S) { int i, e,k; int key = 0; char choice; cout << "请输入对链栈的操作:" << endl; cout << "A.初始化 B.进栈 C.出栈 D.取顶 E.查栈 F.销毁 G.退出" << endl; cin >> choice; while (1) { if (choice == 'A') { InitStack(S); key = 1; cout << "初始化成功!" << endl; } if (choice == 'G') { cout << "你已退出!" << endl; break; } if (!key && choice != 'F') { cout << "栈不存在!请先初始化!" << endl; } cout << "请输入对链栈的操作:" << endl; cout << "A.初始化 B.进栈 C.出栈 D.取顶 E.查栈 F.销毁 G.退出" << endl; cin >> choice; if (choice < 'A' || choice>'G') { cout << "输入不合法!请重新输入:"; cin >> choice; } if (key) { switch (choice) { case 'B': cout << "请输入进栈的元素的个数:"; cin >> i; for (int j = 0; j < i; j++) { cout << "请输入进栈的元素:"; cin >> e; Push(S, e); } cout << "进栈成功!" << endl; break; case 'C': if (StackEmpty(S)) cout << "这是一个空栈!" << endl; else { cout << "请输入出栈的元素的个数:"; cin >> i; if (i > StackLength(S)) { k = StackLength(S); cout << "当前栈最多能出栈" << StackLength(S) << "个元素!" << endl; } else k = i; for (int j = 0; j < k; j++) { Pop(S, e); cout << e << " "; } cout << endl << "出栈成功!" << endl; } break; case 'D': if (StackEmpty(S)) cout << "这是一个空栈!" << endl; else cout << GetTop(S) << " 取顶成功!" << endl; break; case 'E': if (StackEmpty(S)) cout << "这是一个空栈!" << endl; else cout << "当前栈的长度是:" << StackLength(S) << endl; break; case 'F': key = 0; DestroyStack(S); cout << "销毁成功!" << endl; break; } } } }
队列:
1.循环队列测试函数:
void test(SQueue &Q) { int i, e; char choice; int k = 0; int key = 0; cout << "A.初始化 B.进队 C.出队 D.查队 E.取顶 F清空 G.销毁 H.退出" << endl; cin >> choice; while (1) { if (choice == 'A') { InitQueue(Q); cout << "初始化成功!" << endl; key = 1; } if (choice == 'H') {cout << "你已退出!" << endl;break;} if (!key&&choice!='G') { cout << "队列不存在!请先初始化!" << endl; } cout << "请选择对循环队列的操作:" << endl; cout << "A.初始化 B.进队 C.出队 D.查队 E.取顶 F清空 G.销毁 H.退出" << endl; cin >> choice; if (choice < 'A' || choice>'H') { cout << "输入不合法!请重新输入: "; cin >> choice; } if (key) { switch (choice) { case 'B': cout << "请输入进队的元素个数:"; cin >> i; for (int j = 0; j < i; j++) { cout << "请输入进队的元素:"; cin >> e; EnQueue(Q, e); } cout << "进队成功!" << endl; break; case 'C': cout << "请输入出队的元素个数:"; cin >> i; if (i > QueueLength(Q)) { k = QueueLength(Q); cout << "队列最多只能出队" << QueueLength(Q) << "个元素!" << endl; } else k = i; for (int j = 0; j < k; j++) { DeQueue(Q, e); cout << e << " "; } cout << endl << "出队成功!" << endl; break; case 'D': if (QueueEmpty(Q)) { cout << "这是一个空队!" << endl; break; } cout << "当前队的长度是:" << QueueLength(Q) << endl; if (QueueFull(Q))cout << "这是一个满队!" << endl; break; case 'E': if (QueueEmpty(Q)) { cout << "这是一个空队!" << endl; break; } cout << "队头元素:" << GetHead(Q) << endl; cout << "取顶成功!" << endl; break; case 'F': ClearQueue(Q); cout << "清空成功!" << endl; break; case 'G': key = 0; DestroyQueue(Q); cout << "销毁成功!" << endl; break; } } } }
链队测试函数:
void test(LinkQueue &Q) { int i, e; char choice; int k = 0; int key = 0; cout << "A.初始化 B.进队 C.出队 D.查队 E.取顶 F销毁 G.退出 " << endl; cin >> choice; while (1) { if (choice == 'A') { InitQueue(Q); cout << "初始化成功!" << endl; key = 1; } if (choice == 'G') {cout << "你已退出!" << endl;break;} if(!key&&choice!='F') { cout << "队列不存在!请先初始化!" << endl; } cout << "请选择对链队的操作:" << endl; cout << "A.初始化 B.进队 C.出队 D.查队 E.取顶 F销毁 G.退出" << endl; cin >> choice; if (choice < 'A' || choice>'G') { cout << "输入不合法!请重新输入: "; cin >> choice; } if (key) { switch (choice) { case 'B': cout << "请输入进队的元素个数:"; cin >> i; for (int j = 0; j < i; j++) { cout << "请输入进队的元素:"; cin >> e; EnQueue(Q, e); } cout << "进队成功!" << endl; break; case 'C': cout << "请输入出队的元素个数:"; cin >> i; if (i > QueueLength(Q)) { k = QueueLength(Q); cout << "队列最多只能出队" << QueueLength(Q) << "个元素!" << endl; } else k = i; for (int j = 0; j<k; j++) { DeQueue(Q, e); cout << e << " "; } if (!QueueEmpty(Q)) { cout << endl << "出队成功!" << endl; break; } case 'D': if (QueueEmpty(Q)) { cout << "这是一个空队!" << endl; break; } cout << "当前队的长度是:" << QueueLength(Q) << endl; break; case 'E': if (QueueEmpty(Q)) { cout << "这是一个空队!" << endl; break; } cout << "队头元素:" << GetHead(Q) << endl; cout << "取顶成功!" << endl; break; case 'F': key = 0; DestroyQueue(Q); cout << "销毁成功!" << endl; break; } } }