数据结构与算法OG题目

线性结构的应用

删除单链表中的元素

【问题描述】

已知单链表L(带头节点)是一个递增有序表,试编写一算法,删除表中值大于min且小于max的节点(若表中有这样的节点),同时释放被删节点的空间,这里min和max是两个给定参数。

【输入形式】

首先输入正整数T,表示有T组测试数据。输入整数len定义链表长度,然后递增地给出链表的值。接着输入正整数q,表示进行q次操作,每次操作输入一个整数type表示操作类型:输入1,表示输出链表; 输入2, 表示删除链表;在选择删除时同时输入min 和 max的值表示删除范围。例如:输入2 2 4,表示删除大于2小于4的值。最后再次输入1,输出删除元素后的单链表。

【输出形式】

输出建立的单链表和删除元素后的单链表。

【样例输入】

1

5

1 2 3 4 5

3

1

2 2 4

1

【样例输出】

1 2 3 4 5

1 2 4 5

  • 代码示例:
#include <iostream>
#include <malloc.h>
using namespace std;

typedef int ElemType;
typedef struct LNode {
	ElemType data;
	LNode* next;
}LNode;

//链表初始化
LNode* IniLinked(int len) {
	LNode* L;//头结点
	LNode* r;//总是指向尾结点
	LNode* p;//临时结点
	L = (LNode*)malloc( sizeof(LNode) );
	r = L;
	L->next = NULL;

	int x;//存储输入的值
	while (len > 0) {
		cin >> x;
		p = (LNode*)malloc(sizeof(LNode));
		p->data = x;
		p->next = NULL;
		r->next = p;
		r = p;
		len--;
	}
	return L;
}

//删除链表中的区间元素
void DeleteL(int min,int max,LNode* L) {
	LNode* p = (LNode*)malloc(sizeof(LNode));
	p =	L;//行动指针
	LNode* pp;//临时指针
	while (p->next != NULL){
		if (p->next->data > min && p->next->data < max) {
			pp = p->next;
			p->next = p->next->next;
			free(pp);
		}
		else {
			p = p->next;
		}
	}
}

//打印链表
void printLinked(LNode *L) {
	LNode* p = L;
	while (p->next != NULL) {
		cout << p->next->data << " ";
		p = p->next;
	}
	cout << std::endl;
}
int main() {
	//输入正整数T,表示有T组测试数据
	int T = 0;
	cin >> T;
	while (T > 0) {
		//输入整数len定义链表长度
		int len = 0;
		cin >> len;
		//递增地给出链表的值
		LNode* L = IniLinked(len);
		int q,type;
		cin >> q;
		while (q > 0){
			cin >> type;
			if (type == 1) {
				printLinked(L);
			}
			if (type == 2) {
				int min, max;
				cin >> min >> max;
				DeleteL(min, max, L);
			}
			q--;
		}
		T--;
	}
}

约瑟夫问题

【问题描述】

有编号为1, 2…n 的 n 个人按顺时针方向围坐一圈,每人持有一个正整数密码(每个人持有的密码m不一定相同)。开始给定一个正整数 m,从第一个人按顺时针方向自1开始报数,报到m者出列,不再参加报数,这时将出列者的密码作为m,从出列者顺时针方向的下一人开始重新自1开始报数。如此下去,直到所有人都出列。试设计算法,输出出列者的序列。可采用顺序或链式存储结构实现

【输入形式】

第一行输入一正整数a(a<10),表示共有a组测试数据。每组测试数据的第一行有一个整数n(n<100),表示有n个人;第二行有n个数表示每人手中的正整数密码(每人密码大于0小于10000且不一定相等);第三行输入一个正整数m,即上文提到的初始密码m。

【输出形式】

每组测试数据输出一行正整数,表示出列者的序列(每个正整数之间用空格隔开,每行末尾无空格)。

【样例输入】

1

6

2 5 3 7 5 4

3

【样例输出】

3 6 5 2 4 1

  • 代码示例:
#include <iostream>
#include <malloc.h>
using namespace std;

typedef int ElemType;
typedef struct LNode {
	ElemType data;
	LNode* next;
	ElemType index;//索引 
}LNode;

//链表初始化
LNode* IniLinked(int len) {
	LNode* L;//头结点
	LNode* r;//总是指向最后面结点
	LNode* p;//临时结点
	L = (LNode*)malloc(sizeof(LNode));
	r = L;
	L->next = NULL;

	int x;//存储输入的值
	int n = 0;
	while (n < len) {
		cin >> x;
		p = (LNode*)malloc(sizeof(LNode));
		p->data = x;
		p->index = n+1;//存储结点自身的位置 
		p->next = L;//指向头结点 
		r->next = p;
		r = p;
		n++;
	}
	return L;
}

void YSF(LNode* L, int m, int n){
	LNode* p = L;
	LNode* pp;//临时,释放空间的 
	int nn = n ;//一共循环的次数 
	while (nn-- > 0){
	while (m>1){
		if (p->next == L){
			p->next = L->next;
		}
			p = p->next;
		m--;
	}
	m = p->next->data;
	cout << p->next->index <<" ";
	pp = p->next;
	p->next = p->next->next;
	free(pp);
	}
}
int main() {
	//输入正整数a,表示有a组测试数据
	int a = 0;
	cin >> a;
	while (a > 0) {
		//每组测试数据的第一行有一个整数n(n<100),表示有n个人;
		int n;
		cin >> n;
		//第二行有n个数表示每人手中的正整数密码(每人密码大于0小于10000且不一定相等);
		LNode* L = IniLinked(n);
		//第三行输入一个正整数m,即上文提到的初始密码m。
		int m = 0;
		cin >> m;
		
		YSF(L, m, n);
		
		a--;
	}
}

十进制数到N进制数的转换

【问题描述】

将从键盘输入的十进制数转换为N(如二进制、八进制、十六进制)进制数据。(A--10,B--12....Z-35 大小写敏感)

【输入形式】

输入一个正整数num(大于0且在int范围内),再输入一个N(2<=N<=36)表示要转换成多少进制。

【输出形式】

输出转换结果

【样例输入】

3 2
【样例输出】

11

  • 代码示例:
#include <iostream>
#include <stdlib.h>
using namespace std;

#define StackInitSize 50
typedef int StackElementType;

typedef struct {//栈的结构体的定义 
	StackElementType data[StackInitSize];//栈的存储空间 
	int top;//栈顶指针 
}SeqStack;

SeqStack* InitStack(){//栈的初始化 
	SeqStack* s;
	s = (SeqStack* )malloc(sizeof(SeqStack));
	if (s != NULL){
		s->top = -1;
		return s;
	} else {
		cout << "抱歉,申请内存失败,程序运行终止" << endl;
		exit(0);
	}
}

//进栈
void Push(SeqStack* s,StackElementType x){
	
	if (s->top == StackInitSize) {
		cout << "栈满!程序终止运行!" << endl;
		exit(0);
	} else {
		s->top ++;
		s->data[s->top] = x;
	}
}
//设置数组 
void setC(char C[]){
	int i = 0;
	for(;i<10;i++){
		C[i]='0'+i;
	}
	for(;i<37;i++){
		C[i]='A'+i-10;
	}
} 

//弹栈 
int pop (SeqStack* s){
	if (s->top == -1){
		cout << "栈空" <<endl;
		exit(0);
	} else {
		int x = s->data[s->top--];
		return x;
	}
}

int main(){
	SeqStack* s = InitStack();
	char C[36];
	setC(C);
	//cout << "输入num" <<endl;
	int num, radix; // 输入的数和进制数 
	cin >> num;
	//cout << "输入radix" <<endl;
	cin >> radix;
	
	while (1) {

		Push(s, num % radix);
		num /= radix;
		if (num == 0)
			break;
		
	}
	
	while (s->top != -1){
		cout << C[pop(s)];
	}
} 

二叉树的操作

二叉树的创建与遍历

【问题描述】

  1. 以二叉链表为存储结构,实现二叉树的创建、遍历

实验要求:在程序中定义下述函数,并实现要求的函数功能:

CreateTree():按从键盘输入的扩展前序序列,创建二叉树

PreOrderTree():前序遍历树(递归)

InOrderTree():中序(非递归)遍历树

LaOrderTree(): 后序遍历树(递归)

【输入形式】

以扩展二叉树的前序遍历序列作为输入,创建二叉树。

【输出形式】

输出前、中、后序遍历结果

【样例输入】

AB#D##C##

【样例输出】

ABDC

BDAC

DBCA

  • 代码示例:
#include<iostream>
#include<cstdlib> 
using namespace std;
struct BiTNode{
	char data;
	BiTNode* lchild, * rchild;
};
//CreateTree():按从键盘输入的扩展前序序列,创建二叉树
BiTNode* CreateTree() {
	BiTNode* T;
	char ch = getchar();
	if (ch == '#') T = NULL;
	else {
		T = (BiTNode*)malloc(sizeof(BiTNode));
		if (!T) exit(1);
		T->data = ch;
		T->lchild = CreateTree();
		T->rchild = CreateTree();
	}
	return T;
}
void PreOrderTree(BiTNode* root) {//前序递归遍历
	if (root == NULL) return;
	cout << root->data;
	PreOrderTree(root->lchild);
	PreOrderTree(root->rchild);
}
void LaOrderTree(BiTNode* root) {//中序递归遍历
	if (root == NULL) return;
	LaOrderTree(root->lchild);
	LaOrderTree(root->rchild);
	cout << root->data;
}
void InOrderTree(BiTNode* root) {//后序递归遍历
	if (root == NULL) return;
	InOrderTree(root->lchild);
	cout << root->data;
	InOrderTree(root->rchild);
}

void NOrderTree(BiTNode* root) {//中序非递归遍历
	BiTNode* p;
	BiTNode* stack[30];
	int top = 0;
	if (root == NULL) return;
	p = root;
	while (!(p==NULL && top == 0)){
		while (p != NULL) {
			if (top < 30 - 1) {
				stack[top] = p;//将当前指针p压栈
				top++;
			}
			else {
				cout << "栈溢出" << endl;
				return;
			}
			p = p->lchild;//指针指向p的左孩子
		}
		if (top <= 0) return;
		else{
			top--;
			p = stack[top];
			cout << p->data;
			p = p->rchild;
		}
	}

}
int main() {
	BiTNode* root;
	root = CreateTree();
	PreOrderTree(root);
	cout << endl;
	NOrderTree(root);
	cout << endl;
	LaOrderTree(root);
	cout << endl;
}

求二叉树中节点的路径

【问题描述】

在二叉树中,P为二叉树中任一给定结点的值,编写算法求从根结点到P结点之间的路径。

实验要求:以二叉链表作为存储结构

【输入形式】

首先以扩展二叉树的前序遍历序列作为输入,创建二叉树。换一行输入p所指节点的值。

【输出形式】

输出从根节点到p节点的路径(结点序列)。

【样例输入】

AB#D##C##

【样例输出】

ABD

  • 代码示例:
#include<iostream>
#include<cstdlib>
#include<stack>
using namespace std;
stack<char>  s;
struct TreeNode {
	char data;
	TreeNode* lchild;
	TreeNode* rchild;
};
TreeNode* CreateTree() {
	TreeNode* T;
	char ch = getchar();
	if (ch == '#') T = NULL;
	else {
		T = (TreeNode*)malloc(sizeof(TreeNode));
		if (!T) exit(1);
		T->data = ch;
		T->lchild = CreateTree();
		T->rchild = CreateTree();
	}
	return T;
}
void path(TreeNode* root, char ch) {
	TreeNode* s[20];
	int top = -1, i;
	TreeNode* p,* q;
	p = root;
	q = NULL;
	while (p != NULL || top != -1) {
		//遍历左子树
		if (p) {
			s[++top] = p;
			p = p->lchild;
		}
		else {
			p = s[top];
			//右子树为空或者右子树已经访问
			if (p->rchild == NULL || p->rchild == q) {
				if (p->data == ch) {
					for (i = 0; i <= top; i++)	
						cout << s[i]->data;
					return;
				}
				else {
					//q保存已经访问过的结点
					q = p;
					top--;
					p = NULL;
				}
			}
			//遍历右子树
			else p = p->rchild;
		}
	}
}
int main() {
	TreeNode* root;
	root = CreateTree();
	char x;
	cin >> x;
	path(root,x);
}

按层次顺序遍历二叉树

【问题描述】

编写按层次顺序遍历二叉树的算法

实验要求:以二叉链表作为存储结构

【输入形式】

以扩展二叉树前序遍历序列作为输入,创建二叉树。

【输出形式】

输出层次遍历节点的编号,每层按从左到右顺序输出。

【样例输入】

AB#D##C##

【样例输出】

ABCD

  • 代码示例:
#include<iostream>
#include<cstdlib>
#include<queue>
using namespace std;
struct BiTNode {
	char data;
	BiTNode* lchild, *rchild;
};
//CreateTree():按从键盘输入的扩展前序序列,创建二叉树//AB#D##C##
BiTNode* CreateTree() {
	BiTNode* T;
	BiTNode* p;
	char ch = getchar();
	if (ch == '#') T = NULL;
	else {
		T = (BiTNode*)malloc(sizeof(BiTNode));
		if (!T) exit(1);
		T->data = ch;
		T->lchild = CreateTree();
		T->rchild = CreateTree();
	}
	return T;
}

void levelorder(BiTNode* x) {
	if (x == NULL) return;
	queue<BiTNode*> q;
	q.push(x);
	while (!q.empty()) {
		BiTNode* p = q.front();
		q.pop();
		cout << p->data;
		if (p->lchild != NULL) {
			q.push(p->lchild);
		}
		if (p->rchild != NULL) {
			q.push(p->rchild);
		}
	}
}
int main() {
	BiTNode* root;
	root = CreateTree();
	levelorder(root);
}

求二叉树高度及宽度

【问题描述】

二叉树高度是指树中所有节点的最大层数,二叉树宽度是指在二叉树的各层上,具有节点数最多的那一层上的节点总数。编写算法求二叉树高度及宽度。

实验要求:以二叉链表作为存储结构

【输入形式】

以扩展二叉树的前序遍历序列作为输入,创建二叉树。

【输出形式】

输出二叉树的高度和宽度(中间有空格)
【样例输入】

AB#D##C##

【样例输出】

3 2

  • 代码示例:
#include<iostream>
#include<cstdlib>
#include<queue>
using namespace std;
struct TreeNode {
	char data;
	TreeNode* lchild;
	TreeNode* rchild;
};
TreeNode* CreateTree() {
	TreeNode* T;
	char ch = getchar();
	if (ch == '#') T = NULL;
	else {
		T = (TreeNode*)malloc(sizeof(TreeNode));
		if (!T) exit(1);
		T->data = ch;
		T->lchild = CreateTree();
		T->rchild = CreateTree();
	}
	return T;
}
int getDeep(TreeNode* root) {
	if (root == NULL) {
		return 0;
	}
	else {
		int lchild = getDeep(root->lchild);
		int rchild = getDeep(root->rchild);
		return 1 + (lchild > rchild ? lchild : rchild);
	}
}
int levelorder(TreeNode* x) {
	if (x == NULL) return 0;
	queue<TreeNode*> q;
	q.push(x);
	int curCountInQueue = 0;//二叉树当前层已经存在队列中的个数
	unsigned int maxwidth = 0;//节点数最大的层的节点数
	while (!q.empty() ){
		if (curCountInQueue == 0) {
			maxwidth = maxwidth > q.size() ? maxwidth : q.size();
			curCountInQueue = q.size();
		}
		TreeNode* p = q.front();
		q.pop();
		if (p->lchild != NULL) {
			q.push(p->lchild);
		}
		if (p->rchild != NULL) {
			q.push(p->rchild);
		}
		curCountInQueue--;
	}
	return maxwidth;
}
int main() {
	TreeNode* root;
	root = CreateTree();
	cout << getDeep(root);
	cout << " ";
	cout << levelorder(root);
}
posted @   NeverLateThanBetter  阅读(992)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示