C语言---数据结构实验---数制转换---表达式求值---回文判断---二叉树创建遍历

写在前面

数据结构的实现是多种多样的,在本篇实现多种数据结构的过程中会尽可能的使用动态内存的形式,避免使用宏定义的形式,宏定义的形式是很老旧的版本,在实际运用中很少使用,掌握动态运用内存是必备的技能

对于二叉树的遍历创建方法有多种多样,这里使用的是leetcode等平台力荐的递归形式,递归完成二叉树遍历是较为标准和简单的方式

如果对二叉树的遍历不熟悉,最好优先复习二叉树是如何进行递归遍历和创建的

数据结构—手撕图解二叉树

assert函数仅仅是编写代码时便于调试所加,可以删除,不会造成影响

下载链接

实验三Gitee
实验四Gitee

数制转换

问题描述

将十进制数N和其他d进制数之间进行转换是计算机实现计算的基本问题,解决方案很多,其中最简单的方法是除d取余法。例如,(1348)10=(2504)8,其转化过程如下所示:

          N             N div 8            N mod 8
         1348            168                4
         168             21                 0
         21              2                  5
         2               0                  2

从中可以看出,最先产生的余数4是转换结果的最低位,这正好符合栈的“后进先出”的特性。所以可以用顺序栈来模拟这个过程。

题目解析

很简单的题,写一个栈入余数即可

扫描二维码关注公众号,回复: 15908767 查看本文章

需要注意的是,超过十进制的数有字母的参与,因此可以提前写一个数组,然后把栈内元素当成下标,再用下标元素访问数组内元素,就可以达到输出数字和字母的效果

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

//1. 将十进制数N和其他d进制数之间进行转换是计算机实现计算的基本问题,解决方案很多,其中最简单的方法是除d取余法。
// 例如,(1348)10 = (2504)8,其转化过程如下所示:
//N             N div 8            N mod 8
//1348            168                4
//168             21                 0
//21              2                  5
//2               0                  2
//从中可以看出,最先产生的余数4是转换结果的最低位,这正好符合栈的“后进先出”的特性。所以可以用顺序栈来模拟这个过程。

typedef int STDataType;
typedef struct Stack
{
    
    
	STDataType* a;
	int capacity;
	int top;
}Stack;

void StackInit(Stack* pst)
{
    
    
	pst->a = (STDataType*)malloc(sizeof(STDataType) * 4);
	if (pst->a == NULL)
	{
    
    
		perror("malloc fail");
		return;
	}
	pst->capacity = 4;
	pst->top = 0;
}

STDataType StackTop(Stack* pst)
{
    
    
	assert(pst);
	assert(pst->top);
	return pst->a[pst->top - 1];
}

void StackPop(Stack* pst)
{
    
    
	assert(pst);
	assert(pst->top);
	pst->top--;
}

void StackPush(Stack* pst, STDataType x)
{
    
    
	assert(pst);
	if (pst->capacity = pst->top)
	{
    
    
		STDataType* tmp = NULL;
		int newcapacity = pst->capacity * 2;
		tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
		if (tmp == NULL)
		{
    
    
			perror("realloc fail");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}

bool StackEmpty(Stack* pst)
{
    
    
	if (pst->top == 0)
		return true;
	else
		return false;
}

//被除数 dividend 
//除数   divisor 
//商     result
//余数	 remainder

void Calculate(Stack* pst, int dividend, int divisor)
{
    
    
	int remainder;
	while (dividend)
	{
    
    
		remainder = dividend % divisor;
		StackPush(pst, remainder);
		dividend = dividend / divisor;
	}
}

void Print(Stack* pst, int dividend, int divisor)
{
    
    
	char array[16] = {
    
     '0', '1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
	printf("%d(10)=", dividend);
	while (!StackEmpty(pst))
	{
    
    
		printf("%c", array[StackTop(pst)]);
		StackPop(pst);
	}
	printf("(8)\n");
}

int main()
{
    
    
	int dividend = 1348;
	printf("输入十进制数->");
	scanf("%d", &dividend);
	int divisor = 8;
	printf("输入要改变的进制数->");
	scanf("%d", &divisor);
	Stack st;
	StackInit(&st);
	Calculate(&st, dividend, divisor);
	Print(&st, dividend, divisor);
	return 0;
}

表达式求值

题目描述

从键盘输入一个算术表达式并输出它的结果,算术表达式可包含加、减、乘、除、十进制整数和小括号,利用栈实现。

题目解析

本题难度较高,属于高阶题目,需要先转后缀表达式再计算,这里展示一种解法,后续学习了高阶解决方法会更新该题目,下面代码由本人进行一定程度改造所写,基本功能可以实现,如有其他bug自行解决

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define N 30

typedef struct my_stack
{
    
    
	int a[N];
	int top;
}ST;

int isempty(ST* T)
{
    
    
	if (T->top < 0)
		return 1;
	else
		return 0;
}

int isfull(ST* T)
{
    
    
	if (T->top == N - 1)
		return 1;
	else
		return 0;
}

int gettop(ST* T)
{
    
    
	return T->a[T->top];
}

int pop(ST* T)
{
    
    
	int x;
	if (T->top < 0)
	{
    
    
		printf("Zhan is empty,can not pop!\n");
		exit(0);
	}
	else
	{
    
    
		x = T->a[T->top];
		(T->top)--;
		return x;
	}
}

void push(ST* T, int s)
{
    
    
	if (T->top == N - 1)
	{
    
    
		printf("Zhan is full,can not push,you can modify N and then you can push again.\n");
		exit(0);
	}
	else
	{
    
    
		(T->top)++;
		T->a[T->top] = s;
	}
}

void transfer(char* in, char* post)
{
    
    
	ST T;
	int i, j, flag = 0;
	int count;
	int right = 0, left = 0;
	T.top = -1;
	for (i = 0, j = 0; in[i] != '\0'; i++)
	{
    
    
		switch (in[i])
		{
    
    
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			for (count = 0; (in[i] <= '9' && in[i] >= '0') || in[i] == '.'; i++, j++)
			{
    
    
				post[j] = in[i];
				if (in[i] == '.')
					count++;
			}
			i--;
			if (count > 1)
			{
    
    
				printf("数中有两个小数点\n");
				exit(0);
			}
			post[j] = ' ';
			j++;
			flag = 1;
			break;
		case '(':
			if (flag)
			{
    
    
				printf("数字后直接跟括号\n");
				exit(0);
			}
			push(&T, in[i]);
			left++;
			break;
		case ')':
			right++;
			while (gettop(&T) != '(')
			{
    
    
				post[j] = pop(&T);
				j++;
			}
			pop(&T);
			break;
		case '+':

		case '-':
			if (!flag && i != 0)
			{
    
    
				printf("有连续两个运算符之间没有数字\n");
				exit(0);
			}
			while (!isempty(&T) && gettop(&T) != '(')
			{
    
    
				post[j] = pop(&T);
				j++;
			}
			push(&T, in[i]);
			flag = 0;
			break;
		case '*':

		case '/':
			if (!flag)
			{
    
    
				printf("有连续两个运算符之间没有数字\n");
				exit(0);
			}
			while (!isempty(&T) && (gettop(&T) == '/' || gettop(&T) == '*'))
			{
    
    
				post[j] = pop(&T);
				j++;
			}
			push(&T, in[i]);
			flag = 0;
			break;
		default:
			printf("输入非法字符,无法试别\n");
			exit(0);
		}
	}
	if (left != right)
	{
    
    
		printf("左右括号不匹配\n");
		exit(0);
	}
	while (!isempty(&T))
	{
    
    
		post[j] = pop(&T);
		j++;
	}
	post[j] = '\0';
}

float Calculate_zhong(char* post)
{
    
    
	int i, j, top = -1, flag;
	int len;
	float temp, aa[N]={
    
    0};
	char ch[N];
	for (i = 0; post[i] != '\0'; i++)
	{
    
    
		if (post[i] >= '0' && post[i] <= '9')
		{
    
    
			flag = 0;
			j = 0;
			while (post[i] != ' ')
			{
    
    
				if (post[i] == '.')
				{
    
    
					flag = 1;
				}
				ch[j] = post[i];
				i++;
				j++;
			}
			ch[j] = '\0';
			if (flag)
			{
    
    
				for (j = 0; ch[j] != '.'; j++);
				len = j - 1;
				for (j = 0, temp = 0.; ch[j] != '.'; j++)
				{
    
    
					temp += (ch[j] - '0') * (float)pow(10, len - j);
				}
				for (j++, len++; ch[j] != '\0'; j++)
				{
    
    
					temp += (ch[j] - '0') * (float)pow(10, len - j);
				}
			}
			else
			{
    
    
				for (j = 0; ch[j] != '\0'; j++);
				len = j - 1;
				for (j = 0, temp = 0.; ch[j] != '\0'; j++)
				{
    
    
					temp += (ch[j] - '0') * (float)pow(10, len - j);
				}
			}
			top++;
			aa[top] = temp;
		}
		else
		{
    
    
			switch (post[i])
			{
    
    
			case'+':
				temp = aa[top];
				top--;
				temp += aa[top];
				aa[top] = temp;
				break;
			case'-':
				temp = aa[top];
				top--;
				temp = aa[top] - temp;
				aa[top] = temp;
				break;
			case'*':
				temp = aa[top];
				top--;
				temp = temp * aa[top];
				aa[top] = temp;
				break;
			case'/':
				temp = aa[top];
				top--;
				temp = aa[top] / temp;
				aa[top] = temp;
			}
		}
	}
	return aa[top];
}


int main()
{
    
    
	char zhong[N], hou[N];
	float answer;
	printf("需要计算的中缀表达式为:");
	scanf("%s", zhong);
	transfer(zhong, hou);
	answer = Calculate_zhong(hou);
	printf("%.2f\n", answer);
}

回文判断

题目描述

假设称正读和反读都相同的字符序列为“回文”,例如,’abba’和’abcba’是回文,’abcde’和’ababab’则不是回文。请编写一个程序判别读入的一个以’@’为结束符的字符序列是否是“回文”。提示:由于依次输入的字符序列中不含特殊的分隔符,则在判别是否是“回文”时,一种比较合适的做法是,同时利用“栈”和“队列”两种结构。

题目解析

本题也很简单,创建队列和栈两个数据结构,分别取Top比较再Pop,放到while循环里即可

//3. 假设称正读和反读都相同的字符序列为“回文”,例如,’abba’和’abcba’是回文,’abcde’和’ababab’则不是回文。
//请编写一个程序判别读入的一个以’@’为结束符的字符序列是否是“回文”。
//提示:由于依次输入的字符序列中不含特殊的分隔符,则在判别是否是“回文”时,一种比较合适的做法是,同时利用“栈”和“队列”两种结构。\

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

typedef char QueueDataType;
typedef struct QNode
{
    
    
	QueueDataType data;
	struct QNode* next;
}QNode;

typedef struct Queue
{
    
    
	QNode* phead;
	QNode* ptail;
}Queue;

void QueueInit(Queue* pq)
{
    
    
	pq->phead = NULL;
	pq->ptail = NULL;
}

QNode* BuynewQNode(QueueDataType x)
{
    
    
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
    
    
		perror("malloc fail");
		return NULL;
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}

void QueuePush(Queue* pq, QueueDataType x)
{
    
    
	assert(pq);
	QNode* newnode = BuynewQNode(x);
	if (pq->phead == NULL)
	{
    
    
		pq->phead = pq->ptail = newnode;
	}
	else
	{
    
    
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
}

void QueuePop(Queue* pq)
{
    
    
	assert(pq);
	assert(pq->phead);
	pq->phead = pq->phead->next;
}

QueueDataType QueueTop(Queue* pq)
{
    
    
	assert(pq);
	assert(pq->phead);
	return pq->phead->data;
}

bool QueueEmpty(Queue* pq)
{
    
    
	assert(pq);
	if (pq->phead == NULL)
	{
    
    
		return true;
	}
	else
	{
    
    
		return false;
	}
}

typedef char STDataType;
typedef struct Stack
{
    
    
	STDataType* a;
	int capacity;
	int top;
}Stack;

void StackInit(Stack* pst)
{
    
    
	pst->a = (STDataType*)malloc(sizeof(STDataType) * 4);
	if (pst->a == NULL)
	{
    
    
		perror("malloc fail");
		return;
	}
	pst->capacity = 4;
	pst->top = 0;
}

STDataType StackTop(Stack* pst)
{
    
    
	assert(pst);
	assert(pst->top);
	return pst->a[pst->top - 1];
}

void StackPop(Stack* pst)
{
    
    
	assert(pst);
	assert(pst->top);
	pst->top--;
}

void StackPush(Stack* pst, STDataType x)
{
    
    
	assert(pst);
	if (pst->capacity = pst->top)
	{
    
    
		STDataType* tmp = NULL;
		int newcapacity = pst->capacity * 2;
		tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
		if (tmp == NULL)
		{
    
    
			perror("realloc fail");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}

bool StackEmpty(Stack* pst)
{
    
    
	if (pst->top == 0)
		return true;
	else
		return false;
}

void Input(Queue* pq, Stack* ps)
{
    
    
	char ret;
	printf("输入回文字符,以@结尾->");
	while (1)
	{
    
    
		scanf("%c", &ret);
		if (ret == '@')
			break;
		QueuePush(pq, ret);
		StackPush(ps, ret);
	}
}

void Judge(Queue* pq, Stack* ps)
{
    
    
	while (!QueueEmpty(pq))
	{
    
    
		char que = QueueTop(pq);
		QueuePop(pq);
		char st = StackTop(ps);
		StackPop(ps);
		if (que!=st)
		{
    
    
			printf("不是回文\n");
			return;
		}
	}
	printf("是回文\n");
	return;
}

int main()
{
    
    
	Queue q;
	Stack s;
	QueueInit(&q);
	StackInit(&s);
	Input(&q, &s);
	Judge(&q, &s);
	return 0;
}

二叉树的创建、遍历及其它基本操作的实现

问题描述

  1. 以二叉链表作存储结构创建如下二叉树:

在这里插入图片描述

  1. 输出二叉树的中序遍历序列和后序遍历序列,以验证所建二叉树的正确性;

  2. 按二叉树的层次输出所建二叉树各层的结点,要求同层的结点自左向右排列。(提示:用到两个队列P、Q。其中P存放当前层上的结点,Q存放下一层的结点。)

题目解析

本实验就是对二叉树的简单操作,熟悉二叉树即可

二叉树介绍链接:

数据结构—手撕图解二叉树

注意:

创建二叉树的方法有很多种,标准的创建二叉树的方法是用递归调用进行创建,基本原理可以在上文链接寻找

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdbool.h>

typedef struct BinaryTreeNode* QDataType;

typedef struct QNode
{
    
    
	QDataType data;
	struct QNode* next;
}QNode;

typedef struct Queue
{
    
    
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;

typedef char BTDataType;

typedef struct BinaryTreeNode
{
    
    
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

void QueueInit(Queue* pq)
{
    
    
	assert(pq);
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

void QueueDestroy(Queue* pq)
{
    
    
	assert(pq);

	QNode* cur = pq->phead;
	while (cur)
	{
    
    
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}

	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

QNode* BuyQnode(QDataType x)
{
    
    
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
    
    
		perror("malloc fail");
		return NULL;
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}

void QueuePush(Queue* pq, QDataType x)
{
    
    
	assert(pq);
	QNode* newnode = BuyQnode(x);
	if (pq->ptail == NULL)
	{
    
    
		assert(pq->phead == NULL);
		pq->phead = pq->ptail = newnode;
	}
	else
	{
    
    
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}

bool QueueEmpty(Queue* pq)
{
    
    
	if (pq->size == 0)
	{
    
    
		return true;
	}
	return false;
}

void QueuePop(Queue* pq)
{
    
    
	assert(pq);
	assert(!QueueEmpty(pq));

	if (pq->phead->next == NULL)
	{
    
    
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
    
    
		QNode* newhead = pq->phead->next;
		free(pq->phead);
		pq->phead = newhead;
	}

	pq->size--;
}

QDataType QueueFront(Queue* pq)
{
    
    
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->phead->data;
}

QDataType QueueBack(Queue* pq)
{
    
    
	assert(pq);
	return pq->ptail->data;
}

int QueueSize(Queue* pq)
{
    
    
	assert(pq);
	return pq->size;
}

BTNode* BuyNode(BTDataType a)
{
    
    
	BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
	if (newnode == NULL)
	{
    
    
		perror("malloc fail");
		return NULL;
	}
	newnode->data = a;
	newnode->left = NULL;
	newnode->left = NULL;
	return newnode;
}

BTNode* BinaryTreeCreate(BTDataType* a, int* pi)
{
    
    
	if (a[*pi] == '#')
	{
    
    
		(*pi)++;
		return NULL;
	}

	BTNode* root = BuyNode(a[*pi]);
	(*pi)++;

	root->left = BinaryTreeCreate(a, pi);
	root->right = BinaryTreeCreate(a, pi);

	return root;
}

void BinaryTreeDestory(BTNode* root)
{
    
    

	if (root == NULL)
	{
    
    
		return;
	}

	BinaryTreeDestory(root->left);
	BinaryTreeDestory(root->right);
	free(root);
}

void BinaryTreePrevOrder(BTNode* root)
{
    
    
	if (root == NULL)
	{
    
    
		//printf("N ");
		return;
	}

	printf("%c ", root->data);
	BinaryTreePrevOrder(root->left);
	BinaryTreePrevOrder(root->right);
}

void BinaryTreeInOrder(BTNode* root)
{
    
    
	if (root == NULL)
	{
    
    
		//printf("N ");
		return;
	}

	BinaryTreeInOrder(root->left);
	printf("%c ", root->data);
	BinaryTreeInOrder(root->right);
}

void BinaryTreePostOrder(BTNode* root)
{
    
    
	if (root == NULL)
	{
    
    
		//printf("N ");
		return;
	}

	BinaryTreePostOrder(root->left);
	BinaryTreePostOrder(root->right);
	printf("%c ", root->data);
}

void BinaryTreeLevelOrder(BTNode* root)
{
    
    
	Queue q;
	QueueInit(&q);
	if (root)
	{
    
    
		QueuePush(&q, root);
	}
	while (!QueueEmpty(&q))
	{
    
    
		BTNode* front = QueueFront(&q);
		printf("%c ", front->data);
		QueuePop(&q);
		if (front->left)
			QueuePush(&q, front->left);
		if (front->right)
			QueuePush(&q, front->right);
	}
	printf("\n");
	QueueDestroy(&q);
}

int main()
{
    
    
	char ch[] = "AB##CDF###E##";
	int pos = 0;
	BTNode* tree = BinaryTreeCreate(ch, &pos);
	printf("前序遍历:");
	BinaryTreePrevOrder(tree);
	printf("\n");
	printf("中序遍历:");
	BinaryTreeInOrder(tree);
	printf("\n");
	printf("后序遍历:");
	BinaryTreePostOrder(tree);
	printf("\n");
	printf("层序遍历:");
	BinaryTreeLevelOrder(tree);
	printf("\n");
	BinaryTreeDestory(tree);
	tree = NULL;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_73899585/article/details/131836561