C language --- data structure experiment --- number system conversion --- expression evaluation --- palindrome judgment --- binary tree creation traversal

written in front

The implementation of data structures is diverse. In the process of implementing various data structures in this article, the form of dynamic memory will be used as much as possible, and the form of macro definition will be avoided. The form of macro definition is a very old version. Rarely used in practical applications, mastering the dynamic use of memory is an essential skill

There are many ways to create a binary tree traversal. Here we use the recursive form strongly recommended by platforms such as leetcode. Recursively completing the binary tree traversal is a relatively standard and simple way.

If you are not familiar with the traversal of the binary tree, it is best to first review how the binary tree is recursively traversed and created

Data structure - hand-torn graphic binary tree

The assert function is only added to facilitate debugging when writing code, and can be deleted without causing any impact

download link

Experiment 3 Gitee
Experiment 4 Gitee

Number system conversion

Problem Description

Converting the decimal number N to other d-base numbers is a basic problem in computer-implemented calculations. There are many solutions, and the simplest method is to divide by d and take the remainder. For example, (1348) 10 = (2504) 8, the conversion process is as follows:

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

It can be seen from it that the remainder 4 generated first is the lowest bit of the conversion result, which just conforms to the "last in, first out" characteristic of the stack. So you can use a sequential stack to simulate this process.

topic analysis

It's a very simple question, just write a stack and insert the remainder

It should be noted that numbers exceeding the decimal system have letters involved, so you can write an array in advance, then use the elements in the stack as subscripts, and then use the subscript elements to access the elements in the array to achieve the effect of outputting numbers and letters

#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;
}

expression evaluation

topic description

Input an arithmetic expression from the keyboard and output its result. Arithmetic expressions can include addition, subtraction, multiplication, division, decimal integers and parentheses, and are implemented using a stack.

topic analysis

This question is difficult and belongs to an advanced question. It needs to be converted to the suffix expression before calculating. Here is a solution. After learning the advanced solution, the question will be updated. The following code is written by me with a certain degree of modification. The basic functions It can be realized, if there are other bugs, solve it by yourself

#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);
}

Palindrome judgment

topic description

Assume that a character sequence with the same forward reading and reverse reading is called a "palindrome", for example, 'abba' and 'abcba' are palindrome, but 'abcde' and 'ababab' are not palindrome. Please write a program to judge whether the read-in character sequence ending with '@' is a "palindrome". Tip: Since the sequentially input character sequence does not contain special separators, it is more appropriate to use the two structures of "stack" and "queue" when judging whether it is a "palindrome".

topic analysis

This question is also very simple. Create two data structures, queue and stack, respectively take Top and compare them, then Pop them, and put them in the while loop.

//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;
}

Implementation of binary tree creation, traversal and other basic operations

Problem Description

  1. Create the following binary tree with a binary linked list as the storage structure:

insert image description here

  1. Output the in-order traversal sequence and post-order traversal sequence of the binary tree to verify the correctness of the built binary tree;

  2. Output the nodes of each layer of the built binary tree according to the level of the binary tree, requiring the nodes of the same layer to be arranged from left to right. (Hint: Two queues P and Q are used. Among them, P stores the nodes on the current layer, and Q stores the nodes on the next layer.)

topic analysis

This experiment is a simple operation on the binary tree, just familiar with the binary tree

Binary tree introduction link:

Data structure - hand-torn graphic binary tree

Notice:

There are many ways to create a binary tree. The standard way to create a binary tree is to use recursive calls to create it. The basic principle can be found in the link above.

#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;
}

Guess you like

Origin blog.csdn.net/qq_73899585/article/details/131836561