吉林大学大数据专业数据结构算法实现-第三章-线性表,堆栈和队列

第三章-线性表,堆栈和队列


目录

前言&学习心得

1.顺序表的插入算法insert(O(n))

1.1实现功能:

1.2ADL描述:

1.3代码实现:

2.顺序表的删除算法Delete(O(n))

2.1实现功能:

2.2ADL描述:

2.3代码实现:

------------单链表模板-------------

3.单链表的寻第k节点值算法Find(O(n))

3.1实现功能:

3.2ADL描述:

3.3代码实现:

4.单链表的查找算法Search(O(n))

4.1实现功能:

4.2ADL描述:

4.3代码实现:

5.单链表的删除算法Delete

5.1实现功能:

5.2ADL描述:

5.3代码实现:

6.单链表的插入算法insert

6.1实现功能:

6.2ADL描述:​

6.3代码实现:

 ------------双向链表类-------------

7.栈的应用-括号匹配检测算法MatchBrackets(O(n))

7.1实现功能:

7.2ADL描述:

7.3代码实现:

8.栈的应用-波兰后缀表达式的求值算法

8.1实现功能:

8.2ADL描述:

8.3代码实现:

总结



前言&学习心得

这是我用csdn写的第一篇文章,这个分享大概会在23年12月中旬完成.

大数据专业的数据结构理论课程由姜老师独立授课,一方面为了我的期末复习,另一方面为了惠及往后的学弟学妹们,我打算将姜老师讲解的算法ADL+代码复现分享给大家,用于预习与复习,代码经测试应该都可执行测试样例,若有错误请各位斧正.

大部分算法实现用到了STL容器,第一次接触的同学可以在站内自行了解vector,stack,queue等容器.

关于此文章的使用方式,推荐首次接触数据结构的同学在上课前将每章对应的所有算法弄懂,上课时可以使用我的代码结合课堂内容去学习,在课后重要的算法一定要自己多次复现,我的代码只是一个参考,用自己的思路实现才最适合你.


1.顺序表的插入算法insert(O(n))

1.1实现功能:

在顺序表A中下标为k 的结点后插入字段值为item的结点

1.2ADL描述:
1.3代码实现:
void insert(vector<int>& A,int k,int item) {
	int lenth = A.size();//这里lenth为最大下标+1
	if (k<0 || k>lenth-1)
	{
		cout << "插入不合法";
		return;
	}
	//与ADL不同的是我们的数组空间和数据量相同,向后扩充时会越界,所以需要提前扩充空间
	A.resize(lenth + 1);
	//执行此操作后,数组最大下标变为lenth
	for (int i = lenth-1; i >= k + 1; i--)
	{
		A[i + 1] = A[i];
	}
	A[k + 1] = item;
	return;
}

2.顺序表的删除算法Delete(O(n))

2.1实现功能:

删除顺序表A中下标为 k 的结点

2.2ADL描述:

2.3代码实现:
void Delete(vector<int>& A, int k) {
	int lenth = A.size();//这里lenth为最大下标+1
	if (k<0 || k>lenth - 1||lenth==0)
	{
		cout << "删除不合法";
		return;
	}
	//这里不能提前缩小空间,会使最后一个数据丢失!
	for (int i = k; i < lenth-1; i++)
	{
		A[i] = A[i+1];
	}
	A.resize(lenth - 1);
	return;
}

------------单链表模板-------------

接下来是关于单链表的算法,以下是单链表节点结构体(带哨位节点),创建函数(-1停止),打印函数

struct ListNode {//单链表结构体
	int val;
	ListNode* next;
	ListNode() : val(0), next(nullptr) {}
	ListNode(int x) : val(x), next(nullptr) {}
	ListNode(int x, ListNode* next) : val(x), next(next) {}
};

ListNode* build_list() {//单链表创建(有哨位节点)
	ListNode* head = new ListNode(0);//head指向哨位节点,其值为0,值无意义
	int init,follow;
	cin >> init;
	if (init == -1)return NULL;
	head ->next=new ListNode(init);
	ListNode* p = head->next;
	cin >> follow;
	while (follow != -1)
	{
		p->next=new ListNode(follow);
		cin >> follow;
		p = p->next;
	}
	return head;
}

void print_list(ListNode* head) {//单链表打印
	if (head == NULL)return;
	ListNode* p = head->next;
	while (p != NULL)
	{
		cout << p->val << " ";
		p = p->next;
	}
	return;
}

3.单链表的寻第k节点值算法Find(O(n))

3.1实现功能:

 将链表中第k个结点的字段值赋给item,在代码实现中修改了功能,具体见注释.

3.2ADL描述:

3.3代码实现:
int Find(ListNode* head,int k) {//函数内部无法修改外界局部变量,仅可修改全局变量
//为扩展其用途,我们将他修改为返回目标值的函数,在调用后赋值即可,错误情况返回-1
	if (k < 1)
	{
		cout << "存取位置不合法";
		return -1;
	}
	k--;//我在这里没有用额外的临时变量i作计数器,直接用k自减来计数,初始要自减一次
	ListNode* p = head->next;
	while (p != NULL && k--)//while(a--)是我比较常用的循环方式,可以确保循环体重复a次
	{
		p = p->next;
	}
	if (p == NULL)
	{
		cout << "无此节点";
		return -1;
	}
	return p->val;
}

4.单链表的查找算法Search(O(n))

4.1实现功能:

在链表中查找字段值为item的结点并返回其在表中的位置(值为item的节点,是第i个链表节点)

4.2ADL描述:

4.3代码实现:
int Search(ListNode* head,int item) {
	ListNode* p = head->next;
	int i = 1;
	while (p != NULL && p->val != item)
	{
		p = p->next;
		i++;
	}
	if (p != NULL)
	{
		return i;
	}
	cout << "无此节点";
	return -1;
}

5.单链表的删除算法Delete

5.1实现功能:

删除链表中第k个结点并将其字段值赋给item,同上,我们修改了功能,

返回被删除的值,而非赋值给item.

5.2ADL描述:

5.3代码实现:
int Delete(ListNode* head, int k) {
	if (k < 1)
	{
		cout << "删除不合法";
		return -1;
	}
	ListNode* p = head; //与之前不同的是, p的初值是head, 而不是head->next
	k--;//同上,我们又一次去掉了计数器i,使用k来完成循环判断
	while (p->next != NULL && k--)//我们的判断语句变成了p->next非空
	//这是为了让p在删除节点前停下,方便后续逻辑删除
	{
		p = p->next;
	}
	if (p->next == NULL)
	{
		cout << "无此节点";
		return -1;
	}
	ListNode* q = p->next;//用q指到删除位置
	p->next = q->next;//将前位置的next换为删除位置的next--逻辑删除
	int item = q->val;
	free(q);//物理删除
	return item;
}

6.单链表的插入算法insert

6.1实现功能:

在链表中第k 个结点后插入字段值为item的结点 

6.2ADL描述:

6.3代码实现:
void insert(ListNode* head,int k,int item) {
	if (k < 0)
	{
		cout << "插入不合法";
		return;
	}
	ListNode* p = head->next;
	k--;//你懂
	while (p != NULL && k--)
	{
		p = p->next;
	}
	if (p == NULL)
	{
		cout << "插入不合法";
		return;
	}
	ListNode* s = new ListNode(item);//开辟s
	s->next=p->next;//s连上后面的节点
	p->next = s;//s连上前面的节点
	return;
}

 ------------双向链表类-------------

不知道是否会考察,先留一个类给大家,只是多了一个prev前节点

struct ListNode {  
    int val;  
    ListNode* prev;  
    ListNode* next;  
    ListNode() : val(0), prev(nullptr), next(nullptr) {}  
    ListNode(int x) : val(x), prev(nullptr), next(nullptr) {}  
    ListNode(int x, ListNode* prev, ListNode* next) : val(x), prev(prev), next(next) {}  
};

7.栈的应用-括号匹配检测算法MatchBrackets(O(n))

7.1实现功能:

在链表中第k 个结点后插入字段值为item的结点,此处用到stl的stack,不了解的同学可以自学,或者用数组链表模拟.

7.2ADL描述:

7.3代码实现:
bool MatchBrackets(string str) {
	stack<char> s;
	for (auto ch : str)//cpp11的遍历方法,类型名 变量名:数组可完成遍历操作
	{//auto自动类型名,不想思考或者类型名不好写时可以使用
		if (ch == '{' || ch == '[' || ch == '(')s.push(ch);
		//遇到左括号一律压入栈
		if (ch == '}' || ch == ']' || ch == ')')
		{//遇到右括号,弹出栈顶,判断是否匹配,这里仅判断匹配失败的情况
			if (s.empty())return false;//栈空则不匹配
			char hc = s.top();
			s.pop();
			if (ch == '}' && hc != '{')return false;
			if (ch == ']' && hc != '[')return false;
			if (ch == ')' && hc != '(')return false;
		}
	}//没有发生不匹配情况,则说明序列都匹配
	return true;
}

8.栈的应用-波兰后缀表达式的求值算法

8.1实现功能:

求解一后缀表达式(如1234567+-*+-*)的值

8.2ADL描述:

(1)谓词ISOPTOP(x)表示:当x为一操作符时它为真,否则它为假.

(2)函数APPLIED(P,x,y)表示操作符P作用于操作数x和y的结果.

8.3代码实现:
int EPE(vector<char> P) {
	stack<int> s;
	for (auto num : P)
	{
		if (num >= '0' && num <= '9')s.push(num - '0');//是数字则压入栈中
		else
		{//否则为运算符,根据运算符进行运算操作
			char ope = num;
			//每次运算发生时,取出两个栈顶操作数,运算后再压入栈中
			int a = s.top();
			s.pop();
			int b = s.top();
			s.pop();
			if (ope == '+')s.push(b + a);
			if (ope == '-')s.push(b - a);
			if (ope == '*')s.push(b * a);
		}
	}
	return s.top();//最后留在栈内的元素有且只有一个,就是运算结果
}

总结

作为正课的第一章,涉及算法比较基础,大部分偏向于模板,希望同学们多多复现.

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值