实验一 线性表、堆栈和队列的操作与实现

前言

记录实验,同时也是记录常见数据结构算法的实现。


广州大学学生实验报告

开课实验室:计算机科学与工程实验(电子楼418A)
学院 计算机科学与网络工程学院
实验课程 数据结构实验
实验项目 实验一 线性表、堆栈和队列的操作与实现

// DataStruct_experiment.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// StructExperiment.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

#include <iostream>
#include <ctime>
#include <iomanip>
using namespace std;

typedef struct LNode
{
	int data;
	LNode* next;
}LNode, * LinkList;

//插入
void Insert(LinkList &l, LNode* new_node, int n)
{
	// 头结点处不可插入值。判断插入的位置是否为头结点
	while (1)
	{
		if (n == 0)
		{
			cout << "0处是头结点,请重新输入你想插入整数的位置\t位置: ";
			cin >> n;

		}
		else if (n > 11 || n < 1)
		{
			cout << "输入的位置超出链表的长度,请重新输入...\t位置: ";
			cin >> n;
		}
		else break;
	}
	// 寻找n-1处的节点
	LNode* p = new LNode;
	p = l;
	if (p == NULL)
	{
		cout << "空表,退出程序......";
		exit(0);
	}
	int i = 0;
	while (i < n - 1 && p)
	{
		p = p->next;
		++i;
	}

	// 在n处插入新节点,使原来在n处的节点变成n+1
	new_node->next = p->next;
	p->next = new_node;

	cout << "在 " << setw(2) << n << " 处插入值为 " << new_node->data << " 的节点" << endl;
}

//输出链表的内容
void List_show(LinkList& l)
{
	// 判断链表是否为空
	if (!(l->next))
	{
		cout << "出错,此链表为空链表,退出程序......";
		exit(0);
	}
	else
	{
		LNode* p = new LNode;
		p = l->next;
		cout << "链表为:";
		for (int i = 1; p; i++)
		{
			if (p->next)
				cout << p->data << "——";
			else cout << p->data << "\t长度为:" << i << endl;
			p = p->next;
		}
	}
}

//查找
void Search_in_list(LinkList& l)
{
	int element;
	cout << "请输入你想查找的整数: " << endl;
	cout << "————若想退出查找,请输入0————" << endl;
	LNode* p = new LNode;
	p = l->next;
	if (!p)
	{
		cout << "出错,此链表为空链表,退出程序......";
		exit(0);
	}
	else
	{
		while (cin >> element)
		{
			if (element == 0)
			{
				cout << "退出查找......" << endl;
				break;
			}
			else
			{
				int index_not_in = 0; //用于判断查找的值是否在链表中
				for (int i = 1; p; i++)
				{
					if (p->data == element)
					{
						cout << "该整数在表中,且位置为" << i << endl;
						cout << "请再次输入你想查找的整数: " << endl;
						cout << "————若想退出查找,请输入0————" << endl;

					}
					else ++index_not_in;
					p = p->next;
					if (i == index_not_in && p == NULL) //到达链尾时,如果还找不到,说明这个整数不在这个链表中
					{
						cout << "整数" << element << "不在此链表中" << endl;
						cout << "请再次输入你想查找的整数: " << endl;
						cout << "————若想退出查找,请输入0————" << endl;
					}

				}
			}
			p = l->next;
		}
	}
}

//删除
void Delete(LinkList& l)
{
	// 头结点处无数据,且不可删除。判断要删除的位置是否为头结点
	int n;
	cin >> n;
	while (1)
	{
		if (n == 0)
		{
			cout << "0处是头结点,请重新输入你想删除的结点的位置\t位置: ";
			cin >> n;
		}
		else if (n > 10 || n < 1)
		{
			cout << "输入的位置超出链表的长度,请重新输入...\t位置: ";
			cin >> n;
		}
		else
		{
			cout << endl;
			break;
		}
	}

	// 寻找n处的节点
	LNode* p = new LNode;
	p = l;
	int i = 0;
	if (p->next == NULL)
	{
		cout << "出现错误,退出程序......";
		exit(0);
	}
	while (i < n - 1 && p)
	{
		p = p->next;
		++i;
	}
	// 删除n处的结点,使原来在n-1处的节点变成n
	LNode* temp_p = p->next;
	p->next = p->next->next;
	cout << "在 " << setw(2) << n << " 处删除值为 " << temp_p->data << " 的节点" << endl;
	delete temp_p;
}

// 翻转
void Reverse(LinkList& l)
{
	LNode* p = new LNode;
	p = l;
	p = p->next; // p为链表中的第一个结点
	if (p == NULL)
	{
		cout << "该链表为空链表,退出程序......";
		exit(0);
	}

	LNode* p_backward, * p_forward;
	p_backward = NULL;
	while (p)
	{
		p_forward = p->next;
		p->next = p_backward;
		p_backward = p;
		p = p_forward;
	}
	l->next = p_backward;
	cout << "已翻转成功" << endl;
}


int main()
{
	// (1)随机生成十个100~999的三位整数,并且存入链表中
	srand((unsigned(time)));
	LinkList l;	// 链表l(英文字母l)
	l = new LNode;	// 头节点是链表的象征
	l->next = NULL; // 初始化链表
	cout << "(1)" << endl;
	for (int i = 1; i <= 10; i++)
	{
		int random_int = rand() % 900 + 100;
		LNode* p = new LNode;
		p->data = random_int;
		Insert(l, p, i);
	}

	// (2)输出链表的内容
	cout << "(2)" << endl;
	List_show(l);

	// (3)读入一个整数,查看该整数是否在表中,若在,输出其位置,若不在,则说明一下不在
		//加入了可多次输入整数进行判断的功能 
	cout << "(3)" << endl;
	Search_in_list(l);

	// (4) (1)中函数Insert()已经实现了该功能
	cout << "(4)" << endl;
	LNode* p1 = new LNode;
	int location;
	p1->data = 111; //默认插入的值为111
	cout << "你想在链表的哪个位置插入新的元素?\t位置:  ";
	cin >> location;
	Insert(l, p1, location);
	List_show(l);

	//(5)读入一个整数,若该整数在链表里,删除该整数,输出链表的内容;
	cout << "(5)" << endl;
	LNode* p2 = new LNode;
	p2->data = 111; //默认插入的值为111
	cout << "你想删除哪个位置的结点?\t位置:  ";
	Delete(l);
	List_show(l);

	// (6)
	cout << "(6)" << endl;
	Reverse(l);
	List_show(l);
}

2、栈的链式存储结构实现(返回目录🖱)

#include <iostream>
#include <ctime>
#include <iomanip>
using namespace std;

typedef struct LNode
{
	int length;
	int data;
	LNode* next;
}LNode, * LinkStack;

void InitStack(LinkStack &s)
{
	s->next = NULL;
	s->length = 0;
	cout << "链栈初始化成功,长度为0......" << endl;
}
void Push(LinkStack& s, int data)
{
	LNode* p = new LNode;
	p->data = data;
	p->next = s->next;
	s->next = p;
	s->length++;
	cout << "在位置" << setw(3) << s->length << "添加元素" << p->data << endl;
}

void Pop(LinkStack& s)
{
	LNode* p = new LNode;
	p = s->next;
	s->next = p->next;
	s->length--;
	cout << "从栈中弹出元素 " << p->data <<setw(20)<<"深度为"<<s->length<< endl;
	delete p;
}

//输出链栈的内容
void ShowListStack(LinkStack& s)
{
	// 判断链表是否为空
	if (!s->next)
	{
		cout << "栈空......退出程序......"<<endl;
		exit(0);
	}
	else
	{
		LNode* p = new LNode;
		p = s->next;
		cout << "链栈为:" << endl;;
		for (int i = 1; p; i++)
		{
			if (p->next)
				cout <<"| " << p->data << " |\n"<<endl;
			else cout << "| " << p->data << " |\n"<<"-------\t"<<"深度为:" << i << endl;
			p = p->next;
		}
	}
}

int main()
{
	srand(unsigned(time));
	//初始化链栈
	LinkStack s;
	s = new LNode;
	InitStack(s);
	// 入栈
	cout << "(1)\n";
	for (int i = 0; i < 10; i++)
		Push(s, rand() % 900 + 100);
	ShowListStack(s);
	// 出栈
	cout << "(2)\n";
	for (int i = 0; i < 10; i++)
		Pop(s);
	ShowListStack(s);
}

3、队列的链式存储结构的实现(返回目录🖱)

#include <iostream>
#include <ctime>
#include <iomanip>
using namespace std;

//链队结点结构体
typedef struct LQNode
{
	int data;
	LQNode* next;
}LQNode, * LQNodeptr;
//链队结构体
typedef struct LinkQueue
{
	LQNodeptr head;
	LQNodeptr rear;
}LinkQueue;

//初始化
void InitLQ(LinkQueue &lq)
{
	lq.head = lq.rear = new LQNode; //头结点
	lq.head->next =  lq.rear->next = NULL;
}

//入队
void Insert(LinkQueue &lq, int data)
{
	LQNode* p = new LQNode;
	p->data = data;
	p->next = NULL;
	lq.rear->next= p;
	lq.rear = p;
	cout << "在队尾加入结点: " << data << endl;
}

//输出链队
void ShowLQ(LinkQueue &lq)
{
	LQNode* p = new LQNode;
	p = lq.head->next;
	cout << "链队:";
	int length = 0;
	while (p)
	{
		++length;
		if (p != lq.rear)
			cout << p->data << "—";
		else cout << p->data << "\t长度为:"<<length<<endl;
		p = p->next;
	}
}

//翻转
void Reverse(LinkQueue &lq)
{
	LQNode* p = new LQNode; 
	LQNode* q = new LQNode;
	LQNode* r = new LQNode;
	LQNode* p1 = new LQNode;
	p = lq.head;  // 头指针
	p1 = p->next; // 先保存原链队的第一个结点,因为最后需要让尾指针指向它
	q = p->next;
	lq.head->next = NULL;
	while (q)
	{
		r = q->next;
		q->next = p;
		p = q;
		q = r;
	}
	lq.rear = p1;
	p1->next = NULL;
	lq.head->next = p; //将头指针指向尾指针的前一个结点
}
int main()
{
	srand(unsigned(time));
	LinkQueue lq;
	InitLQ(lq);
	//初始化
	InitLQ(lq);
	for (int i = 0; i < 10; i++)
	{
		Insert(lq, rand() % 900 + 100);
	}
	//输出队列
	ShowLQ(lq);
	//翻转
	Reverse(lq);
	//输出
	ShowLQ(lq);
}

4、线性表、栈和队列的应用实现:(返回目录🖱)
(1) 用随机函数生成10个3位整数(100~999),把这些整数存于单链表中,然后读入一个整数,以该值为基准把单链表分割为两部分,所有小于该值的结点排在大于或等于该值的结点之前。

#include <iostream>
#include <ctime>
#include <iomanip>
using namespace std;

// 链式结点(可用于表示链表)
typedef struct LNode
{
	int data;
	LNode* next;
}LNode, * LinkList;

//链栈(用于声明链栈的头结点,头结点不含数据,故无data变量)
typedef struct Stack
{
	LNode* next;
	int depth;
} *LinkStack;


//往单链表中添加元素
void Insert_LinkList(LinkList& l, LNode* new_node, int n)
{
	LNode* p = new LNode;
	p = l;
	for (int i = 1; i < n; i++)
	{
		p = p->next;
	}
	new_node->next = p->next;
	p->next = new_node;
}

//输出单链表
void Show_LinkList(LinkList& l)
{
	// 判断链表是否为空
	if (!(l->next))
	{
		cout << "出错,此链表为空链表,退出程序......";
		exit(0);
	}
	else
	{
		LNode* p = new LNode;
		p = l->next;
		cout << "链表为:";
		for (int i = 1; p; i++)
		{
			if (p->next)
				cout << p->data << "——";
			else cout << p->data << "\t长度为:" << i << endl;
			p = p->next;
		}
	}
}

//向栈中添加元素
void Push(LinkStack& s, int data)
{
	LNode* p = new LNode;
	p->data = data;
	p->next = s->next;
	s->next = p;
	s->depth++;
	//cout << "在位置" << setw(3) << s->depth << "添加元素" << p->data << endl;
}

//在栈中弹出元素
int Pop(LinkStack& s)
{
	LNode* p = new LNode;
	p = s->next;
	s->next = p->next;
	s->depth--;
	//cout << "从栈中弹出元素 " << p->data << setw(20) << "深度为" << s->depth << endl;
	return p->data;
}

//输出链栈的内容
void ShowListStack(LinkStack& s)
{
	// 判断链表是否为空
	if (!s->next)
	{
		cout << "栈空......退出程序......" << endl;
		exit(0);
	}
	else
	{
		LNode* p = new LNode;
		p = s->next;
		cout << "链栈为:" << endl;;
		for (int i = 1; p; i++)
		{
			if (p->next)
				cout << "| " << p->data << " |\n" << endl;
			else cout << "| " << p->data << " |\n" << "-------\t" << "深度为:" << i << endl;
			p = p->next;
		}
	}
}

//以某值为基准把单链表分割为两部分
void Devide(LinkList& l,int n)
{
	// 初始化装载大于n结点的栈 s_big
	LinkStack s_big = new Stack;
	s_big->next = new LNode;
	s_big->next = NULL;
	s_big->depth = 0;
	// 初始化装载小于n结点的栈 s_small
	LinkStack s_small = new Stack;
	s_small->next = new LNode;
	s_small->next = NULL;
	s_small->depth = 0;

	LNode* p = new LNode;
	p = l->next;
	//如果链表长度为0或1,则无法分割
	if (p==NULL || p->next==NULL)
	{
		cout << "链表长度为0或1,无法分割...." << endl;
		exit(0);
	}
	while (p)
	{
		int temp = p->data;
		if (temp >= n)
		{
			Push(s_big, temp);
			cout << "在元素 大 于"<<n<<"的栈的位置" << setw(3) << s_big->depth << "添加元素" << p->data << endl;
			p = p->next;
		}
		else
		{
			Push(s_small, temp);
			cout << "在元素 小 于" << n << "的栈的位置" << setw(3) << s_small->depth << "添加元素" << p->data << endl;
			p = p->next;
		}
	}
	ShowListStack(s_big);
	ShowListStack(s_small);
	LNode* p_ = new LNode;
	p_ = l->next;
	while (s_small->next)
	{
		p_->data = Pop(s_small);
		cout << "从元素 小 于"<<n<<"的栈中弹出元素 " << p_->data << setw(20) << "此时 小 栈深度为" << s_small->depth << endl;
		p_ = p_->next;
	}
	while (s_big->next)
	{
		p_->data = Pop(s_big);
		cout << "从元素 大 于" << n << "的栈中弹出元素 " << p_->data << setw(20) << "此时 大 栈深度为" << s_big->depth << endl;
		p_ = p_->next;
	}
}
int main()
{
	srand(unsigned(time));
	LinkList l = new LNode;
	l->next = NULL;
	for (int i = 0; i < 10; i++)
	{
		LNode* p = new LNode;
		p->data = rand() % 900 + 100;
		Insert_LinkList(l, p, i + 1);
	}
	// 显示原链表
	Show_LinkList(l);

	//小的放300前面,大的放300后面
	Devide(l, 300);
	Show_LinkList(l); 
cout <<"分割已完成。。。";

(2) 假设一个字符串中可以包含三种括号:( )[ ]{},且这三种括号可以按任意次序嵌套使用(如:“…[…{…}…[…]…]…(…)” 为合法嵌套,“…[…{… )…[…]…]…(…)”为不合法嵌套)。编写判别给定表达式中所含括号是否正确配对出现的算法,如果是合法嵌套则返回为true,如果是不符合法嵌套则返回为false。

#include<iostream>
using namespace std;

typedef struct SNode
{
	char ch;
	int depth;
	SNode* next;
}SNode, *Stack;

void InitStack(Stack& s)
{
	s = new SNode;
	s->next = NULL;
	s->ch = NULL;
	s->depth = 0;
}

bool StackEmpty(Stack s)
{
	if (s->next == NULL)
	{
		return true;
		cout << "栈空..." << endl;
	}
	else return false;
}

void Push(Stack& s, char ch)
{
	SNode* p = new SNode;
	p->next = NULL;
	p->ch = ch;
	p->next = s->next;
	s->next = p;
	s->depth++;
	cout << "在栈中放入字符 \"" << ch << "\" \t栈深度为:" << s->depth << endl;
}

void Pop(Stack& s)
{
	SNode* p = new SNode;
	p = s->next;
	cout << "弹出元素" << p->ch << endl;
	s->next = p->next;
	delete p;
}

char GetTop(Stack s)
{
	return s->next->ch;
}

bool Matching()
{
	Stack s;
	InitStack(s);
	cout << "请键入字符...按#退出\t";
	char ch;
	int flag = 1;
	cin >> ch;
	while (ch!='#'&& flag)
	{
			switch (ch)
			{
			case'(':
			case'[':
			case'{':
			{
				Push(s, ch);
				cout << "请继续键入字符...按#退出\t";

			}; break;
			case')':
				if (!StackEmpty(s) && GetTop(s) == '(')
					Pop(s);
				else
				{
					flag = 0;
					cout << "括号" << ch << "不匹配";
				}; break;
			case']':
				if (!StackEmpty(s) && GetTop(s) == '[')
					Pop(s);
				else
				{
					flag = 0;
					cout << "括号" << ch << "不匹配";
				}; break;
			case'}':
				if (!StackEmpty(s) && GetTop(s) == '{')
					Pop(s);
				else
				{
					flag = 0;
					cout << "括号" << ch << "不匹配";
				}; break;
			}
			cin >> ch;
	}
	if (StackEmpty(s) && flag) return 1;
	else return 0;
}

int main()
{
	if (Matching()) cout << "匹配成功";
	else cout << "匹配失败";
}

}

(3)用队列求解迷宫问题的最短路径
代码雏形出来了,但是调试了四个小时还是没解决那个关键bug……

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫咪钓鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值