第五周代码(二叉树后续 + 分治一)

2023/11/6-11/7        周一和周二

GDPU数据结构实验9  二叉树

第三四题(第一二题在第四周代码里面)

【参考代码】 

注意:二叉树的以前的ElemType改成DataType,其他两个头文件的ElemType都改成指针,可以返回根结点的地址。方便遍历左右孩子。使代码可以被复用

.c文件
#include<stdio.h>
#include<malloc.h>
typedef char DataType; //注意以前的ElemType改成DataType,是二叉树的
#define MaxQueueSize 20
#define MaxSize 20

#include "tree.h"
typedef LPBTreeNode *ElemType; //注意其他两个头文件的ElemType都改成指针,可以返回根结点的地址。方便遍历左右孩子
#include "queue.h"
#include "Stack.h"

//层序遍历 广搜思想
void LayerOrder(LPBTreeNode *T)
{
    Queue Q;
    QueueInitiate(&Q); // 初始化队列
    LPBTreeNode *p;
    
    if (T != NULL) 
	{
        QueueAppend(&Q, T); // 根节点入队
        
        while (QueueNotEmpty(Q)) 
		{
            QueueDelete(&Q, &p); // 出队并访问结点
            printf("%c ", p->data); // 输出结点数据
            
            if (p->lchild != NULL) 
			 // 左孩子非空,左孩子入队
                QueueAppend(&Q, p->lchild);
            
            
            if (p->rchild != NULL) 
			 // 右孩子非空,右孩子入队
                QueueAppend(&Q, p->rchild);
            
        }
    }
    printf("\n");
}

void inorderNoRecursion(LPBTreeNode *root)
{
	Stack s;
	StackInitiate(&s);
	LPBTreeNode *p = root;
	while(isEmpty(s) || p)
	{
		if(p)
		{
			push(&s, p);
			p = p->lchild;
		}
		else
		{
			pop(&s, &p);
			visit(p);
			p = p->rchild;
		}
	}
}

int main()
{
	LPBTreeNode *T;
	printf("请输入扩展先序历序列:");
	T=createbintree();
	PrintBiTree(T, 0);  //打印二叉树
	printf("\n");
	
	printf("层序遍历:");
	LayerOrder(T);
	
	printf("中序遍历非递归");
	inorderNoRecursion(T);
}
tree.h文件
typedef struct LBinaryTreeNode
{
	DataType data;  /*数据域 */
	struct LBinaryTreeNode *lchild;//左孩子
	struct LBinaryTreeNode *rchild;//右孩子
}LPBTreeNode;

//访问结点
void visit(LPBTreeNode *t)
{
	printf("%c	",t->data);
}

//先序遍历算法
void preorder(LPBTreeNode *t)
{
	if (t == NULL) 
		return ;
	visit(t);
	preorder(t->lchild);
	preorder(t->rchild);
}

//中序遍历算法
void inorder(LPBTreeNode *t)
{
	if (t == NULL) 
		return ;
	inorder(t->lchild);
	visit(t);
	inorder(t->rchild);
}

//后序遍历算法
void postorder(LPBTreeNode *t)
{
	if (t == NULL) 
		return ;
	postorder(t->lchild);
	postorder(t->rchild);
	visit(t);
}

// 计算叶子结点数并打印
void caculateLeafNum(LPBTreeNode *root, int *leafNum)
{
	if(root == NULL)
		return ;
	if(root->lchild == NULL && root->rchild == NULL)
	{
		(*leafNum)++;
		visit(root);
	}
	caculateLeafNum(root->lchild, leafNum);
	caculateLeafNum(root->rchild, leafNum);
}

//二叉树的打印
void PrintBiTree(LPBTreeNode *root, int n)
{
	int i;
	if(root == NULL)
		return ;
	PrintBiTree(root->rchild, n+1);
	
	//访问根结点
	for(i = 0; i <= n-1; i++)
		printf("	");
	if(n >= 0)
	{
		printf("---");
		printf("%c\n", root->data);
	}
	PrintBiTree(root->lchild, n+1);
}

/*从根开始递归创建二叉树 */
LPBTreeNode *createbintree(void)
{
	LPBTreeNode *pbnode;
	char ch;
	scanf("%c", &ch);
	if(ch == '#') 
		pbnode = NULL;
	else
	{
		pbnode = (LPBTreeNode *) malloc(sizeof(LPBTreeNode));
		if( pbnode == NULL )
		{
			printf("0ut of space!\n");
			return pbnode;
		}
		pbnode->data = ch;  
		pbnode->lchild = createbintree();	//构造左子树
		pbnode->rchild = createbintree();	//构造右子树
			
	}
	return pbnode;
}


queue.h文件
//循环队列定义,队首指针和队尾指针
typedef struct
{
	ElemType queue[MaxQueueSize];
	int front;
    int rear; 
    int count;  //计数器
}Queue;

//初始化队列
void QueueInitiate(Queue *Q)
{
	Q->count = 0;
	Q->front = 0;
	Q->rear = 0;
}

//检查队列是否为空
int QueueNotEmpty(Queue Q)
{
	if(Q.count == 0)
		return 0;
	else
		return 1;
}

//入队
int QueueAppend(Queue *Q, ElemType x)
{
	if ( Q->count>0 && Q->rear == Q->front )  //检查是否申请成功
	{
		printf("队列已满无法插入!\n");
		return 0;
	}
	else
	{
		Q->queue[Q->rear] = x;
		Q->rear = ( Q->rear + 1 ) % MaxQueueSize;
		Q->count++;
		return 1;
	}
}

//出队
int QueueDelete(Queue *Q, ElemType *x)
{
	if (Q->count == 0)  //队列中只有一个节点
	{
		printf("循环队列已空!\n");
		return 0;
	}
	else
	{
		*x = Q->queue[Q->front];  
		Q->front = ( Q->front + 1 ) % MaxQueueSize;  
		Q->count--;
		return 1;
	}
}
//获取队头元素
int QueueGet(Queue *Q, ElemType *d)
{
	if (Q->count == 0)  //队列中只有一个节点
	{
		printf("循环队列已空!\n");
		return 0;
	}
	else
	{
		*d = Q->queue[Q->front]; 
		return 1;
	}
}
Stack.h文件
//typedef int Elemtype;
typedef struct Stack
{
	ElemType stack[MaxSize];
	int top;  //栈顶下标值
}Stack;
//栈初始化
void StackInitiate(Stack *S)	
{
	S->top = 0;
}
//返回栈的大小
int StackSize(Stack S)
{
	return S.top;
}
//判断栈是否为空
int isEmpty(Stack S)
{
	if(S.top <= 0) //空栈的情况
		return 0;
	else
		return 1;
}
//清空栈
void ClearStack(Stack *S)
{
	S->top = 0;
}
//入栈
int push(Stack *S, ElemType x)
{
	if (S->top >= MaxSize)
	{
		printf("栈已满无法插入!\n");
		return 0;
	}
	else
	{
		S->stack[S->top] = x;
		S->top++;
		return 1;
	}
}
//出栈
int pop(Stack *S, ElemType *d)
{
	if(S->top <= 0)
	{
		printf("栈已空无数据元素出栈!\n");
		return 0;
	}
	else
	{
		S->top--;  //先减后弹出
		*d = S->stack[S->top];  //将栈顶元素值赋给*d
		return 1;
	}
}
//取栈顶元素
int getTopElem(Stack S, ElemType *d)
{
	if(S.top <= 0)
	{
		printf("栈已空!\n");
		return 0;
	}
	else
	{
		*d = S.stack[S.top - 1];  //将栈顶元素值赋给*d
		return 1;
	}
}
【运行结果】

2023/11/8-9         周三周四

学习分治算法

尝试了几种经典题型:

1.递归求累加,求阶乘

【参考代码】

累加

add(int num)
{
    sum = 0;
    if(num <= 1)
    {
        sum += num;
        return sum;
    }
    
    else
        return sum += num + add(num-1);
}

阶乘

int fac(int n)
{
	if(n==0||n==1)  
		return 1;
	else
		return n*fac(n-1);
}

2.汉诺塔问题

【参考代码】

参考了这个大佬的代码

#include <iostream>
using namespace std;

void hanoiTower(int num, char a, char b, char c)
{
	if (num == 1)
	{
		cout << "第1个盘从" << a << "->" << c;
	}
	else {
		//递归n-1个盘子,由a放置到b
		hanoiTower(num - 1, a, c, b);
		//a上剩下的一个盘子,由a拿到c,输出出来
		cout << "第" << num << "个盘从" << a << "->" << c << endl;
		//b上有n-1个盘子,将这n-1个盘子递归放到c上
		hanoiTower(num - 1, b, a, c);
	}
}

int main()
{
	char a = 'A', b = 'B', c = 'C';
	hanoiTower(3, a, b, c);
}

【运行结果】

 

3.快速排序算法

思路
1.找一个基准值(一般为第一个)
2.把比基准值小的放左边
3.把比基准值大的放右边
4.对左右部分进行递归

#include <iostream>
using namespace std;

int a[] = { 19, 97, 9, 17, 1, 8 };

void quickSort(int a[], int low, int high)
{
	//漏了这段
	if (low >= high)
		return;
	int left = low, right = high;
	int p = a[left];
	while (left < right)
	{
		
		//大于p值就不动
		while (left < right && a[right] >= p)
		{
			--right;
		}

			//把比基准值小的放左边
			if (a[right] < p)
			{
				a[left] = a[right];
			}
		
		//小于p值就不动
		while (left < right && a[left] <= p)
		{
			++left;
		}
			//把比基准值大的放右边
			if (a[left] > p)
			{
				a[right] = a[left];
			}
		
	}
	
	//插进中间的空位
	if (left >= right)
	{
		a[left] = p;
		//break;
	}
	//对左右部分进行递归
	quickSort(a, low, left-1);
	quickSort(a, left+1, high);

}

int main()
{
	quickSort(a, 0, 5);
	for (int i = 0; i < sizeof(a) / sizeof(int); i++)
		cout << a[i] << " ";
}

【运行结果】

4.二分查找算法(折半查找算法)

【参考代码】

#include <stdio.h>
//递归查找
int recursionBinarySearch(int a[], int low, int high, int key)
{
	if(low > high)
	{
		return -1;//一定是-1,若为0,查找第一个数字的时候就会和index=0冲突
	}
	
		int mid = (low + high) / 2;
		if(a[mid] == key)
		{
			return mid;
		}	
		else if(a[mid] < key)
		{
			return recursionBinarySearch(a, mid+1, high, key);
		}	
		else
		{
			return recursionBinarySearch(a, low, mid-1, key);
		}
	
}
 
//无递归二分查找
int binarySearch(int a[], int low, int high, int key)
{
	while(low <= high)
	{
		int mid = (low + high) / 2;
		if(a[mid] == key)
		{
			return mid;
		}
		else if(a[mid] < key)
		{
			low = mid+1;
		}
		else
		{
			high = mid-1;
		}
	}
	return -1;
}
 
int main()
{
    int a[5]={1, 2, 3, 4, 5};
    int key = 0;
    int cnt = 3;
    while(cnt)//输入输出3次
	{
		scanf("%d", &key);
	    int res1 = binarySearch(a, 0, 4, key);
		int res2 = recursionBinarySearch(a, 0, 4, key);
		
	    if(res1 == -1 || res2 == -1)
	    	printf("Notfind");
	    else
	    {
	    	printf("Find index:%d\n", res1);
	    	printf("Recursion Find index:%d\n", res2);
		}
		cnt--;	
	}
    
	return 0;
}

【运行结果】

5.归并排序算法

思想
(1)把前一半数组进行排序
(2)把后一半数组进行排序
(3)将前后两部分归并到一个新的有序数组,
然后将这个有序数组再“赋值”给原来的数组,归并排序完成。


#include <iostream>
#include <stdlib.h>
using namespace std;

int arr[] = { 9, 5, 2, 7, 12, 4, 3, 1, 11 };
//合并
void merge(int arr[], int tempArr[], int left, int mid, int right)
{
	// 标记左半区第一个未排序的元素
	int l_pos = left;
	// 标记右半区第一个未排序的元素
	int r_pos = mid + 1;
	// 临时数组元素的下标
	int index = left;
	// 合并
	while (l_pos <= mid && r_pos <= right)//比较值全部要<=
	{
		if (arr[l_pos] < arr[r_pos])
		{
			tempArr[index] = arr[l_pos];
			index++; l_pos++;
		}
		else
		{
			tempArr[index] = arr[r_pos];
			index++; r_pos++;
		}
	}
	
	// 合并左半区剩余的元素
	while (l_pos <= mid)	//比较值全部要<=
	{
		tempArr[index] = arr[l_pos];
		index++; l_pos++;
	}
	// 合并右半区剩余的元素
	while (r_pos <= right)	//比较值全部要<=
	{
		tempArr[index] = arr[r_pos];
		index++; r_pos++;
	}	
	// 把临时数组中合并后的元素复制回原来的数组
	while (left <= right)	//比较值全部要<=
	{
		arr[left] = tempArr[left];
		left++;
	}
}

//数组分开
void divide(int arr[], int tempArr[], int left, int right)
{
	if (left < right)
	{
		int mid = (left + right) / 2;
		divide(arr, tempArr, left, mid);//错误:mid-1
		divide(arr, tempArr, mid+1, right);
		merge(arr, tempArr, left, mid, right);
	}
}

//创建临时数组
void makeTempArr(int arr[], int n)
{
	int* tempArr = (int*)malloc(n * sizeof(int));
	if (tempArr)
	{
		divide(arr, tempArr, 0, n-1);
		free(tempArr);
	}
	else
	{
		cout << "临时数组创建失败";
	}
}
int main()
{
	makeTempArr(arr, 9);
	for (int i = 0; i < 9; i++)
		cout << arr[i] << " ";
}

【运行结果】

 2023/11/10        周五

GDPU数据结构实验10 构建哈夫曼树和哈夫曼编码待补充。。。。

【参考代码】

#include <stdio.h>
#include <malloc.h>
#define MaxNode 20
#define MaxInt 99

struct HtNode{
	int ww;
	int parent, lchild, rchild;
};

struct HtTree {
	int root;
	//char code[];
	struct HtNode ht[MaxNode];
};
typedef struct HtTree PHtTree;

PHtTree* huffman(int m, int* w)//m为结点个数
{
	PHtTree* pht;
	int i, j, x1, x2, m1, m2;
	pht = (PHtTree*)malloc(sizeof(PHtTree));
	if (pht == NULL)
	{
		printf("Out of space!!\n");
		return pht;
	}
	for (i = 0; i < 2 * m - 1; i++)
	{
		pht->ht[i].lchild = -1;
		pht->ht[i].rchild = -1;
		pht->ht[i].parent = -1;
		if (i < m)
		{
			pht->ht[i].ww = w[i];
		}
		else
		{
			pht->ht[i].ww = -1;
		}
	}

	for (i = 0; i < m - 1; i++)
	{
		m1 = MaxInt;
		m2 = MaxInt;
		x1 = -1;
		x2 = -1;
		for (j = 0; j < m + i; j++)
		{
			if (pht->ht[j].ww < m1 && pht->ht[j].parent == -1)
			{
				m2 = m1;
				x2 = x1;
				m1 = pht->ht[j].ww;
				x1 = j;
			}
			else if (pht->ht[j].ww < m2 && pht->ht[j].parent == -1)
			{				
				m2 = pht->ht[j].ww;
				x2 = j;
			}

		}	pht->ht[x1].parent = m + i;
			pht->ht[x2].parent = m + i;
			pht->ht[m + i].ww = m1 + m2;
			pht->ht[m + i].lchild = x1;
			pht->ht[m + i].rchild = x2;	
	}
	pht->root = m + i;
	return pht;
}

int main() {
	int w[] = { 7, 19, 2, 6, 32, 3, 21, 10 };//叶子
	PHtTree* pht;
	pht = huffman(8, w);
	int i;
	printf("weight parent lchild rchild\n");
	for (i = 0; i < 2*8-1; i++)
	{
		printf(" %d\t%d\t%d\t%d\n", pht->ht[i].ww, pht->ht[i].parent,
			pht->ht[i].lchild, pht->ht[i].rchild);
	}
	printf("哈夫曼编码为:");

	/*for (i = 0; i < 8; i++)
		printf("weight = %d  Code = %d", pht->ht[i].ww, );*/

}

【运行结果】

2023/11/11        周六男生节 

蓝桥杯周赛

第一题

 【运行结果】 : 1

第二题

 【参考代码】

#include <iostream>
using namespace std;

int min(int a, int b, int c)
{
  int m;
  if(a<b)
    m = a;
  else
    m = b;
  if(c < m)
    m = c;
  
  return m;
}

int main()
{
  // 请在此输入您的代码
  //暴力
  int T, res = 0, prize;
  int a, b, c;
  cin >> T;
  while(T--)
  {
    cin >> prize;
    a = b = c = prize;
    //某猫
    if(a >= 500)
      a = a - a / 10;
    //某东
    
    if(b >= 1000)
      b = b - 150;
    //某音
    if(c == 1111)
      c = 0;
    else
      c = c - c / 20;
      
    int tmp = min(a, b, c); 
    res += tmp;
	
  }

  cout << res;
  return 0;
}

第三题

【参考代码】

判断条件一定要加等于,别问我为什么,就是这样卡住的😂

#include <iostream>
using namespace std;
int main()
{
  // 请在此输入您的代码
  //选最大的出牌
  int x, y, x2, y2;
  int Sfirst, Jfirst;
  char a[] = {'3','4','5','6','7','8','9','X','J','Q','K','A','2','M','F'};
  int T;
  cin >> T;
  while(T--)
  {
    char s,d,j,k;
    cin >> s >> d >> j >> k;
    if (s == d || ( s == 'M' && d == 'F') || ( s == 'F' && d == 'M'))
    {
      cout << "ShallowDream" << endl;
      continue;
    }
    if (s != d && ( j == 'M' && k == 'F' ) || ( j == 'F' && k == 'M' ))
    {
      cout << "Joker" << endl;
      continue;
    }

    //ShallowDream的部分
    for(x = 0; x < sizeof(a)/sizeof(char); x++)
    {
      if(a[x] == s)
        break;
    }
    for(y = 0; y < sizeof(a)/sizeof(char); y++)
    {
      if(a[y] == d)
        break;
    }

    if(x >= y) // 又输在大于等于上
      Sfirst = x;
    else
      Sfirst = y;
    //Joker部分的
    for(x2 = 0; x2 < sizeof(a)/sizeof(char); x2++)
    {
      if(a[x2] == j)
        break;
    }
    for(y2 = 0; y2 < sizeof(a)/sizeof(char); y2++)
    {
      if(a[y2] == k)
        break;
    }

    if(x2 >= y2)
      Jfirst = x2;
    else
      Jfirst = y2;
    
    if(Sfirst >= Jfirst)
      cout << "ShallowDream"<< endl;
    else
      cout << "Joker"<< endl;;
  
    
  }
  return 0;
}

【运行结果】

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值