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;
}
【运行结果】