算法笔记第七章数据结构

1.栈
简单计算器,实现C++代码如下:

#include<cstdio>
#include<iostream>
#include<string>
#include<stack>
#include<queue>
#include<map>
using namespace std;
struct node {
	bool flag;
	double num;
	char op;
};
stack<node>s;
map<char,int>op;
string str;
queue<node>q;
void Change() {
	int i;
	node temp;
	for (i = 0; i < str.length();) {
		if (str[i] >= '0' && str[i] <= '9') {
			temp.flag = true;
			temp.num = str[i++] - '0';
			while (i < str.length() && str[i] >= '0' && str[i] <= '9') {
				temp.num = temp.num * 10 + (str[i] - '0');
				i++;
			}
			q.push(temp);
		}
		else {
			temp.flag = false;
			while (!s.empty() && op[str[i]] <= op[s.top().op]) {
				q.push(s.top());
				s.pop();
			}
			temp.op = str[i];
			s.push(temp);
			i++;
		}
	}
	while (!s.empty()) {
		q.push(s.top());
		s.pop();
	}
}
double Cal() {
	double temp1, temp2;
	node cur, temp;
	while (!q.empty()) {
		cur = q.front();
		q.pop();
		if (cur.flag == true) s.push(cur);
		else {
			temp2 = s.top().num;
			s.pop();
			temp1 = s.top().num;
			s.pop();
			if (cur.op == '+') temp.num = temp1 + temp2;
			else if (cur.op == '-') temp.num = temp1 - temp2;
			else if (cur.op == '*')temp.num = temp1 * temp2;
			else temp.num = temp1 / temp2;
			s.push(temp);
		}
	}
	return s.top().num;
}		
int main() {
	op['+'] = op['-']=1;
	op['*'] = op['/'] = 2;
	while (getline(cin, str), str != "0") {
		for (string::iterator it = str.end()-1; it != str.begin(); it--) {
			if (*it == ' ') {
				str.erase(it);
			}
		}
		while (!s.empty()) {
			s.pop();
		}
		Change();
		printf("%.2f\n", Cal());
	}
}

首先读入数据后将其存储为字符串的形式,引入。因为数据中存在数字与计算操作符因此要存储为string形式。其次对数据进行检测,将数据中的空格删除掉,使用string的迭代器iterator从后往前进行检测,检测到为空格就用erase函数擦除该迭代器对应的元素。因为是循环输入数据,因此设定的栈需要进行检查,因为最后得到的结果在栈顶,因此栈一般都是非空,所以需要检查是否为空,若空的话就把元素都pop出来。这样就完成了全部的准备工作。因为输入的是后缀表达式,因此需要先将其转换为计算方便的后缀表达式,Change()函数的功能就是进行中缀表达式转后缀表达式的操作。由于数据有两种可能:操作数与操作符。因此需要建立一个结构体node,里面定义三个量,分别为double型的操作数变量,char型的操作符变量,bool类型的flag变量。flag变量用来显示读入的字符为操作数还是操作符,操作数赋为true,操作符赋为false。然后进行检测,如果是操作数的话,那该字符的字符值应该在‘0’与‘9’之间,可以等于这两个数。判断完其为操作数后并不能直接压入队列(定义一个队列用来存放后缀表达式)因为其可能与之后的数组成十位、百位等数因此需要判断其下一位是否也为操作符,将该数赋值给一个temp临时存储变量。进行一个while循环,如果是操作数的话就temp10再加上该操作数形成新的temp。循环推出后将temp压入queue中。如果是操作符的话就与栈顶的操作符判断,此时需要定义操作符的优先级。本题只实现了±/四则运算,所以可以定义一个map<char,int>的映射,定义一个描述优先级的map op。将±的优先级赋值为1,*/的优先级赋值为2.这样就可以区分运算赋的优先级了。如果读入的字符是操作符且优先级高于栈顶操作符的优先级就将栈顶操作符弹出到queue中去,一直弹出直到栈顶操作符的优先级低于读入操作符的优先级为止。将读入操作符压入栈中。最后判断都做完之后判断栈是不是空的,一般都会存在一个操作符或多个残余,将栈剩下的操作符压入queue中去,如此中缀表达式就转成了后缀表达式。接着进行计算操作,Cal()函数即为计算后缀表达式的函数,计算后缀表达式的步骤为读取queue中的后缀表达式,若为操作数则将其压入栈中,若为操作符,则根据操作符的定义进行计算,连取两个栈顶元素,第二个为第一操作数第一个为第二操作数。计算完后将计算的结果压入栈中,如此直到读完queue为止。
【】string的长度为length函数,其他的是size函数。

2.队列
3.链表
动态链表,使用指针实现。

#include<cstdio>
#include<stdlib.h>
struct node {
	int data;
	node* next;
};
node* Create(int Array[]) {
	node* head, *pre, *p;
	head = new node;
	head->next = NULL;
	pre = head;
	for (int i = 0; i < 5; i++) {
		p = new node;
		p->data = Array[i];
		p->next = NULL;
		pre->next = p;
		pre = p;
	}
	return head;
}
int search(node* head, int x) {
	int count = 0;
	node* p = head->next;
	while (p != NULL) {
		if (p->data == x)count++;
		p = p->next;
	}
	return count;
}
void insert(node* head, int pos, int x) {
	node* q,*temp;
	q = head;
	for (int i = 0; i < pos - 1; i++) {
		q = q->next;
	}
	temp = new node;
	temp->data = x;
	temp->next = q->next;
	q->next = temp;
}
void del(node* head, int x) {
	node* q = head->next;
	node* pre = head;
	while (q != NULL) {
		if (q->data == x) {
			pre->next = q->next;
			delete(q);
			q = pre->next;
		}
		else {
			pre = q;	
			q = q->next;
		}
	}
}
int main() {
	int Array[5] = { 5,4,3,2,1 };
	node* l=Create(Array);
	l = l->next;
	while (l != NULL) {
		printf("%d", l->data);
		l = l->next;
	}
}

链表创建、插入、查找。
静态链表,使用hash实现,数组的下标就是地址。
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include<cstdio>
struct node {
	char data;
	int next;
	bool flag;
}; node p1[99999];
int main() {
	char data;
	int	N;
	int address1,address2;
	int address;
	int next;
	int temp = 0;
	for (int i = 0; i < 99999; i++) {
		p1[i].flag = false;
	}
	scanf("%d %d %d", &address1 ,&address2 ,& N);
	for (int j = 0; j < N; j++) {
		scanf("%d %c %d", &address, &data, &next);
		p1[address].data = data;
		p1[address].next = next;
	}
	p1[address1].flag = true;
	temp = address1;
	while (temp != -1) {
		temp = p1[temp].next;
		p1[temp].flag = true;
	}
	temp = address2;
	while (1) {
		if (p1[temp].flag == 1) {
			if (temp != -1) {
				printf("%05d", temp);
				break;
			}
			else {
				printf("-1");
				break;
			}
		}
		else {
			temp = p1[temp].next;
		}
	}
}

在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include<cstdio>
#include<algorithm>
using namespace std;
struct node {
	int data;
	int next;
	int address;
	bool flag;
} p[100000];
bool cmp(node a, node b) {
	if (a.flag == false || b.flag == false) {
		return a.flag > b.flag;
	}
	else {
		return a.data < b.data;
	}
}
int main() {
	int begin;
	int N;
	int address;
	int s;
	int count=0;
	int m;
	scanf("%d %d", &N, &begin);
	for (int i = 0; i < N; i++) {
		scanf("%d", &address);
		scanf("%d %d", &p[address].data, &p[address].next);
		p[address].address = address;
	}
	s = begin;
	for (int j = 0; j < 100000; j++) {
		p[j].flag = false;
	}
	while (s != -1) {
		p[s].flag = true;
		s = p[s].next;
		count++;
	}
	sort(p, p + 100000, cmp);
	if (count!=0) {
		printf("%d %05d\n", count, p[0].address);
		for (m = 0; m < count-1; m++) {
			p[m].next = p[m + 1].address;
			printf("%05d %d %05d\n", p[m].address, p[m].data, p[m].next);
		}
		m = 4;
		p[4].next = -1;
		printf("%05d %d %d\n", p[m].address, p[m].data, p[m].next);
	}
	else {
		printf("0 -1");
	}
	return 0;
}

【】在使用scanf时,若读取的某个变量值在之后的读取的变量中要用到,则需要分两个scanf来写,先读取该变量,再读取要用到该变量的变量(通常是数组下标)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值