数据结构课程设计

提醒1:本篇所有内容已开源至gitee,项目地址

提醒2:本篇篇幅极长,请点击目录查看

提醒3:提醒1和提醒2是您参考本篇课设的两种方法

一 线性结构 链表

Joseph环

任务:编号是1,2,…,n的n个人按照顺时针方向围坐一圈,每个人只有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。设计一个程序来求出出列顺序。要求:利用单向循环链表存储结构模拟此过程,按照出列的顺序输出各个人的编号。

测试数据:m的初值为20,n=7 ,7个人的密码依次为3,1,7,2,4,7,4,则正确的输出是什么?

要求:输入数据:建立输入处理输入数据,输入m的初值,n ,输入每个人的密码,建立单循环链表。

输出形式:建立一个输出函数,将正确的输出序列

提供的数据结构:

typedef struct Node
{
   int data;
   int password;
   struct Node *next;
}Node, *LinkList;

基本操作:初始化单链表;给每个人赋密码;确定需要处理的人数;确定开始的上限值;得到正确的顺序;输出结果。

import java.util.*

class Node(var value: Int, var password: Int) {
    var next: Node? = null
}

fun main(args: Array<String>) {
    println("请输入报数上限值m")
    var M: Int = Integer.valueOf(readLine())
    println("请输入人数n:")
    val N: Int = Integer.valueOf(readLine())
    //val data = intArrayOf(3, 1, 7, 2, 4, 7, 4) // 编写初期为了方便直接加入测试数据
    //var data = Array(N) { readLine()!!.split(' ').map { it.toInt() }.toIntArray() } // 此法读入后数据类型为IntArray,与所需Int不匹配
    var data = IntArray(N)
    println("请输入每个人持有的密码,以空格分隔:")
    val scan = Scanner(System.`in`) // 使用Java的Scanner类
    var i = 0
    data[i] = scan.nextInt()
    while(scan.hasNextInt())
    {
        i += 1
        data[i] = scan.nextInt()
    }
    val t = Node(1, data[0]) // 头结点单独拿出来,方便形成循环链表
    var x: Node? = t
    for (i in 2..N) x = Node(i, data[i - 1]).also { x!!.next = it } //建立单向链表
    x!!.next = t // 最后一个结点的next指向第一个节点,形成循环链表
    println("出列的顺序为:")
    while (x !== x!!.next) {
        for (i in 1 until M) x = x!!.next
        // 报数到M,此人出列
        print(x!!.next!!.value.toString() + " ")
        M = x.next!!.password // 上限更新为此人密码
        x.next = x.next!!.next
    }
    println()
    println("最后的获胜者是:" + x!!.value)
}

git项目中为应用到安卓的工程,您可以下载源代码参考

效果图
效果图1

二 栈和队列

迷宫问题求解

任务:可以输入一个任意大小的迷宫数据,用非递归的方法求出一条走出迷宫的路径,并将路径输出;

要求:在上交资料中请写明:存储结构、基本算法(可以使用程序流程图)、源程序、测试数据和结果、算法的时间复杂度、另外可以提出算法的改进方法。

#include <iostream>
#include <graphics.h>
//#include <easyx.h>
#include <conio.h>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#define MAXNUM 3600
using namespace std;

struct Point {
	int x, y, sum;
	bool dirc[4]; // direction: [0]-up [1]-down [2]-left [3]-right
	char ch;
	bool visit[4];
	Point& operator=(Point& test) // 重载等号
	{
		x = test.x;
		y = test.y;
		sum = test.sum;
		ch = test.ch;
		for (int i = 0; i < 4; i++)
		{
			dirc[i] = test.dirc[i];
			visit[i] = test.visit[i];
		}
		return *this;
	}
}point[MAXNUM][MAXNUM];

typedef struct {
	Point base[MAXNUM];
	int top;
}Sqstack;


// 对话框交互
LRESULT CALLBACK CBTHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	HWND hwnd = (HWND)wParam;
	if (nCode == HCBT_ACTIVATE)
	{
		SetDlgItemText(hwnd, IDYES, L"好的");
		SetDlgItemText(hwnd, IDNO, L"退出");
		SetDlgItemText(hwnd, IDOK, L"好的");
	}
	return 0;
}
int MyMessageBox(HWND hwnd, const TCHAR* szText, const TCHAR* szCaption, UINT uType)
{
	int ret;
	HHOOK hHook = SetWindowsHookEx(WH_CBT, CBTHookProc, nullptr, GetCurrentThreadId());
	ret = MessageBoxEx(hwnd, szText, szCaption, uType, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
	UnhookWindowsHookEx(hHook);
	return ret;
}

// 载入图片
IMAGE maze_wall, maze_ground, maze_path;
void _InitImage()
{
	loadimage(&maze_wall, _T("IMG"), _T("wall"));
	loadimage(&maze_ground, _T("IMG"), _T("ground"));
	loadimage(&maze_path, _T("IMG"), _T("path"));
}

// 栈相关操作函数
Sqstack InitStack() // 栈的初始化
{
	Sqstack S;
	S.top = -1;
	return S;
}

bool isEmpty(Sqstack S) // 判断栈空
{
	if (S.top == -1) return true;
	return false;
}

void PushIntoStack(Sqstack& S, Point x) // 入栈
{
	if (S.top == MAXNUM - 1)
	{
		/*MyMessageBox(0, TEXT("栈已满!"), TEXT("Warning!"), MB_OK | MB_SETFOREGROUND);
		exit(0);*/
		cout << "栈满!";
		return;
	}
	S.base[++S.top] = x;
}

void PopOutofStack(Sqstack& S) // 出栈
{
	if (S.top == -1)
	{
		cout << "栈空!";
		return;
	}
	S.top--;
}

Point GetStackTop(Sqstack S) // 取栈顶元素
{
	return S.base[S.top];
}

char Maze[MAXNUM][MAXNUM];
Sqstack S = InitStack();
int cnt = 0;
// 迷宫使用函数
void MazePrint(int n, int m)
{
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
			cout << Maze[i][j];
		cout << endl;
	}
	//initgraph(n * 15, m * 15);
	//_InitImage();
	initgraph(m * 15, n * 15);
	//initgraph(m * 15, n * 15, SHOWCONSOLE);
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			switch (Maze[i+1][j+1])
			{
			case '.':
				putimage(j * 15, i * 15, &maze_ground);
				break;
			case '#':
				putimage(j * 15, i * 15, &maze_wall);
				break;
			case '@':
				putimage(j * 15, i * 15, &maze_path);
				break;
			}
}

void GetMaze(int n, int m) // 输入迷宫
{
	cout << "请输入迷宫(.代表空地,#代表障碍:)" << endl;
	for(int i=1; i<=n; i++)
		for (int j = 1; j <= m; j++)
		{
			cin >> point[i][j].ch;
			point[i][j].x = i;
			point[i][j].y = j;
			Maze[i][j] = point[i][j].ch;
		}
}

void InitMaze(int n, int m)
{
	int a[4] = { 1, -1, 0, 0 }, b[4] = { 0, 0, -1, 1 };
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			point[i][j].sum = 0;
			for (int k = 0; k < 4; k++)
			{
				if (point[i][j].ch == '.' && point[i + a[k]][j + b[k]].ch == '.')
				{
					point[i][j].dirc[k] = 1;
					point[i][j].visit[k] = 0;
					point[i][j].sum++;
				}
				else
				{
					point[i][j].dirc[k] = 0;
					point[i][j].visit[k] = 1;
				}
			}
		}
	}
}

void SeekBegin(int& x, int& y, int n, int m)
{
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			if (Maze[i][j] == '.' && (i == 1 || i == n || j == 1 || j == m))
			{
				x = i;
				y = j;
				return;
			}
}

void SeekEnd(int& x, int& y, int n, int m)
{
	for (int i = n; i >= 1; i--)
		for (int j = m; j >= 1; j--)
			if (Maze[i][j] == '.' && (i == 1 || i == n || j == 1 || j == m))
			{
				x = i;
				y = j;
				return;
			}
}

void Solve(int n, int m)
{
	//int x = 1, y = 1;
	int x, y, xend, yend;
	SeekBegin(x, y, n, m);
	SeekEnd(xend, yend, n, m);
	PushIntoStack(S, point[x][y]);
	cnt++;
	if (isEmpty(S)) cout << "NULL";
	while (!isEmpty(S))
	{
		Point top = GetStackTop(S);
		if (!point[x][y].visit[0] && point[x][y].dirc[0])
		{
			point[x++][y].visit[0] = 1;
			point[x][y].visit[1] = 1;
			PushIntoStack(S, point[x][y]);
			cnt++;
		}
		else if (!point[x][y].visit[1] && point[x][y].dirc[1])
		{
		//cout << 1 << endl;
			point[x--][y].visit[1] = 1;
			point[x][y].visit[0] = 1;
			PushIntoStack(S, point[x][y]);
			cnt++;
		}
		else if (!point[x][y].visit[2] && point[x][y].dirc[2])
		{
			point[x][y--].visit[2] = 1;
			point[x][y].visit[3] = 1;
			PushIntoStack(S, point[x][y]);
			cnt++;
		}
		else if (!point[x][y].visit[3] && point[x][y].dirc[3])
		{
			point[x][y++].visit[3] = 1;
			point[x][y].visit[2] = 1;
			PushIntoStack(S, point[x][y]);
			cnt++;
		}
		else if (point[x][y].visit[0] && point[x][y].visit[1] && point[x][y].visit[2] && point[x][y].visit[3])
		{
			PopOutofStack(S);
			if (isEmpty(S))
			{
				cout << "No way." << endl;
				(MyMessageBox(0, TEXT("找不到路了啦!"), TEXT("呜呜呜"), MB_OK | MB_SETFOREGROUND));
				break;
			}
		}
		x = GetStackTop(S).x;
		y = GetStackTop(S).y;
		//if (point[x][y].x == n || point[x][y].y == m)
		if (point[x][y].x == xend && point[x][y].y == yend)
		{
			cout << "Success" << endl;
			while (!isEmpty(S))
			{
				Point anspr; // ansprint
				anspr.x = GetStackTop(S).x;
				anspr.y = GetStackTop(S).y;
				PopOutofStack(S);
				Maze[anspr.x][anspr.y] = '@';
			}
			(MyMessageBox(0, TEXT("找到走法并绘制完成!"), TEXT("乌拉!"), MB_OK | MB_SETFOREGROUND));
			MazePrint(n, m);
			//cout << cnt << endl;
			break;
		}
	}
}

int main()
{
    //std::cout << "Hello World!\n";
	if (MyMessageBox(0, TEXT("请输入60*60以内大小的迷宫"), TEXT("Hello!"), MB_YESNO | MB_SETFOREGROUND) == IDYES)
	{
		//initgraph(750, 750);
		//fill(point[0], point[0] + MAXNUM * MAXNUM, '#');
		_InitImage();
		memset(point, '#', sizeof(point));
		int n, m;
		cout << "请输入行数和列数:" << endl;
		cin >> n >> m;
//initgraph(n * 15, m * 15, SHOWCONSOLE);
		while (n > 60 || m > 60 || n < 0 || m < 0)
		{
			MyMessageBox(0, TEXT("请重新输入!"), TEXT("Bia!"), MB_OK | MB_SETFOREGROUND);
			cout << "请重新输入行数和列数:" << endl;
			cin >> n >> m;
		}
		GetMaze(n, m);
		InitMaze(n, m);
		//MazePrint(n, m);
		Solve(n, m);
		system("pause");
		closegraph();
	}
	return 0;
}

效果图:

效果图2

三 树型结构

家谱

采用树型结构实现如下系统功能:

1)输入文件以存放最初家谱中各成员的信息。 成员的信息中均应包含以下内容:姓名、出生日期、婚否、地址、健在否、死亡日期(若其已死亡)也可附加其它信息、但不是必需的。
2)实现数据的存盘和读盘。
3)以图形方式显示家谱。
4)显示第n代所有人的信息。
5)按照姓名查询,输出成员信息(包括其本人、父亲、孩子的信息)。
6)按照出生日期查询成员名单。
7)输入两人姓名,确定其关系。
8)某成员添加孩子。
9)删除某成员(若其还有后代,则一并删除)。
10)修改某成员信息。
11)按出生日期对家谱中所有人排序。
12)打开一家谱时,提示当天生日的健在成员。

测试要求:

1)建立至少10个成员的数据,以较为直观的方式显示结果,并提供文稿形式以便检查。
2)对界面的要求是:有合理的提示,每个功能可以设立菜单,根据提示,可以完成相关的功能要求。

generation.h

#pragma once
typedef struct Infomation {
    char name[20]; // 姓名
    char sex; // 性别,M男F女
    char birth[10]; // 出生日期
    bool wedding; // 婚否 1是0否
    char address[20]; // 地址
    bool alive; // 健在 1是0否
    char death[10]; // 死亡日期,先决条件:alive
}Info;
typedef struct binode {
    Info person;
    struct binode* lc, * rc;
}BitNode, *BiTree;

void newLeft(BiTree& p, Info One); // 添加左孩子
void newRight(BiTree& p, Info One); // 添加右孩子
BiTree createTree(Info Human[]); // 建树

void outputTitle(); // 输出信息
void outputInfo(BiTree p); // 输出结点

void levelTrav(BiTree Tree); // 层次遍历
void showNGene(BiTree p, int n); // 显示第n代所有人的信息
void showFamily(BiTree Tree); // 显示整个家谱

// 按照姓名查询,输出成员信息(包括其本人、父亲、孩子的信息)
BiTree findParent(BiTree BT, BitNode* p); // 找到结点父亲
BiTree searchName(BiTree BT, char* str); // 按照姓名查询
void findChild(BiTree p, BiTree* child); // 找到结点孩子
void searchThreeGeneration(BiTree Tree); // 三代查询

// 按照出生日期查询成员名单
BiTree findBirthday(BiTree BT, char* birth); // 按照出生日期查询
void searchBirthday(BiTree Tree); // 查询成员

// 输入两人姓名,确定其关系
bool isSameFather(BiTree BT, BitNode* p, BitNode* q); // 判断是否具有共同父亲
void judgeRelationship(BiTree Tree); // 确定两个人的关系

void addChild(BiTree& Tree); // 某成员添加孩子
void deletePerson(BiTree& Tree); //删除某成员
void updateInfo(BiTree Tree); // 修改某成员信息

// 按出生日期对家谱中所有人排序
void transportBirth(BiTree BT, char bir[][20], int& i); // 生日信息
void sortBirthday(BiTree Tree, int n); // 排序

generation.cpp

#include "generation.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>

void newLeft(BiTree& p, Info One)
{
    BitNode* q = new BitNode;
    q->person = One;
    q->lc = q->rc = NULL;
    p->lc = q;
}

void newRight(BiTree& p, Info One)
{
    BitNode* q = new BitNode;
    q->person = One;
    q->lc = q->rc = NULL;
    p->rc = q;
}

BiTree createTree(Info Human[])
{
    BiTree Bt;
    Bt = new BitNode;
    Bt->person = Human[0];
    Bt->lc = Bt->rc = NULL;
    newLeft(Bt, Human[1]);
    newRight(Bt, Human[2]);
    newLeft(Bt->lc, Human[3]);
    newRight(Bt->lc, Human[4]);
    newLeft(Bt->rc, Human[5]);
    newRight(Bt->rc, Human[6]);
    newLeft(Bt->lc->lc, Human[7]);
    newRight(Bt->lc->lc, Human[8]);
    newLeft(Bt->lc->rc, Human[9]);
    newRight(Bt->lc->rc, Human[10]);
    newRight(Bt->rc->lc, Human[11]);
    return Bt;
}

void outputTitle()
{
    //printf("姓名     性别 出生日期    婚否    地址    健在  死亡日期\n");
    printf("%-10s", "姓名");
    printf("%-5s", "性别");
    printf("%-10s", "出生日期");
    printf("%-5s", "婚否");
    printf("%-12s", "地址");
    printf("%-5s", "健在");
    printf("%s\n", "死亡日期");
}

void outputInfo(BiTree p)
{
    if (p)
    {
        printf("%-10s", p->person.name);
        //printf("%-5c", p->person.sex);
        if (p->person.sex == 'M')
            printf("%-6s", "男");
        else
            printf("%-6s", "女");
        printf("%-10s", p->person.birth);
        //printf("%-5d", p->person.wedding);
        if (p->person.wedding)
            printf("%-6s", "是");
        else
            printf("%-6s", "否");
        printf("%-12s", p->person.address);
        //printf("%-5d", p->person.alive);
        if (p->person.alive)
            printf("%-6s", "是");
        else
            printf("%-6s", "否");
        printf("%s\n", p->person.death);
    }
    else printf("查无此人\n");
}

void levelTrav(BiTree Tree)
{
    BiTree Q[20];
    int front = 0, rear = 0;
    outputTitle();
    //printf("姓名        性别      出生日期     婚否      地址      健在       死亡日期\n");
    if (Tree)
    {
        rear++;
        Q[rear] = Tree;
        while (front != rear)
        {
            front = (front + 1) % 20;
            BitNode* p = Q[front];
            outputInfo(p);
            if ((rear + 1) % 20 != front && p->lc != NULL)
            {
                rear = (rear + 1) % 20;
                Q[rear] = p->lc;
            }
            if ((rear + 1) % 20 != front && p->rc != NULL)
            {
                rear = (rear + 1) % 20;
                Q[rear] = p->rc;
            }
        }
    }
}

void showNGene(BiTree p, int n)
{
    static int depth = 0;
    depth++;
    if (p)
    {
        if (depth == n)
            outputInfo(p);
        showNGene(p->lc, n);
        showNGene(p->rc, n);
    }
    depth--;
}

void showFamily(BiTree Tree)
{
    std::queue<BiTree> q1, q2;
    int i = 0;
    if (Tree)
    {
        q1.push(Tree);
        while (!q1.empty())
        {
            while (!q1.empty())
            {
                q2.push(q1.front());
                q1.pop();
            }
            i++;
            switch (i)
            {
            case 1:
                printf("第%d代:         ", i);
                break;
            case 2:
                printf("第%d代:      ", i);
                break;
            case 3:
                printf("第%d代:   ", i);
                break;
            case 4:
                printf("第%d代:", i);
                break;
            default:
                break;
            }
            while (!q2.empty())
            {
                BitNode* tmp = q2.front();
                q2.pop();
                printf("%s ", tmp->person.name);
                if (tmp->lc)
                    q1.push(tmp->lc);
                if (tmp->rc)
                    q1.push(tmp->rc);
            }
            printf("\n");
        }
    }
}

BiTree findParent(BiTree BT, BitNode* p)
{
    BiTree L_result, R_result;
    if (!BT || BT == p)
        return NULL;
    if (BT->lc == p || BT->rc == p)
        return BT;
    else
    {
        L_result = findParent(BT->lc, p);
        R_result = findParent(BT->rc, p);
        return L_result ? L_result : (R_result ? R_result : NULL);
    }
}

BiTree searchName(BiTree BT, char* str)
{
    BiTree L_result, R_result;
    if (!BT)
        return NULL;
    if (strcmp(BT->person.name, str) == 0)
        return BT;
    else
    {
        L_result = searchName(BT->lc, str);
        R_result = searchName(BT->rc, str);
        return L_result ? L_result : (R_result ? R_result : NULL);
    }
}

void findChild(BiTree p, BiTree *child)
{
    child[0] = p->lc ? p->lc : NULL;
    child[1] = p->rc ? p->rc : NULL;
}

void searchThreeGeneration(BiTree Tree)
{
    char name[20];
    BiTree parent, trnode, child[2];
    printf("请输入被查找成员的姓名:");
    scanf_s("%s", name, 20); // VS认为scanf是不安全的
    trnode = searchName(Tree, name);
    if (!trnode)
        printf("查无此人\n");
    else
    {
        parent = findParent(Tree, trnode);
        findChild(trnode, child);
        printf("此人信息为:\n");
        outputTitle();
        outputInfo(trnode);
        printf("他的父亲结点的信息为:\n");
        if (parent)
            outputTitle();
        outputInfo(parent);
        printf("他的左孩子的信息为:\n");
        if (child[0])
            outputTitle();
        outputInfo(child[0]);
        printf("他的右孩子的信息为:\n");
        if (child[1])
            outputTitle();
        outputInfo(child[1]);
    }
}

BiTree findBirthday(BiTree BT, char* birth)
{
    BiTree L_result, R_result;
    if (!BT)
        return NULL;
    if (strcmp(BT->person.birth, birth) == 0)
        return BT;
    else
    {
        L_result = findBirthday(BT->lc, birth);
        R_result = findBirthday(BT->rc, birth);
        return L_result ? L_result : (R_result ? R_result : NULL);
    }
}

void searchBirthday(BiTree Tree)
{
    char birth[10];
    printf("请输入要查找的成员的生日:");
    scanf_s("%s", birth, 10);
    BitNode* p = findBirthday(Tree, birth);
    if (!p)
    {
        printf("查无此人\n");
        return;
    }
    outputTitle();
    outputInfo(p);
}

bool isSameFather(BiTree BT, BitNode* p, BitNode* q)
{
    BiTree f1 = findParent(BT, p), f2 = findParent(BT, q);
    if (f1 == f2) return true;
    else return false;
}

void judgeRelationship(BiTree Tree)
{
    char name1[20], name2[20];
    printf("请输入第一个人的姓名:");
    scanf_s("%s", name1, 20);
    printf("请输入第二个人的姓名:");
    scanf_s("%s", name2, 20);
    BiTree s1 = searchName(Tree, name1), s2 = searchName(Tree, name2);
    if (isSameFather(Tree, s1, s2)) 
        printf("两人是亲兄弟\n");
    else
    {
        BiTree f1 = findParent(Tree, s1), f2 = findParent(Tree, s2);
        if (isSameFather(Tree, f1, f2))
            printf("两人是堂兄弟\n");
        else if (s1->lc == s2)
            printf("%s是%s的左孩子\n", s2->person.name, s1->person.name);
        else if (s2->lc == s1)
            printf("%s是%s的左孩子\n", s1->person.name, s2->person.name);
        else if (s1->rc == s2)
            printf("%s是%s的右孩子\n", s2->person.name, s1->person.name);
        else if (s2->rc == s1)
            printf("%s是%s的右孩子\n", s1->person.name, s2->person.name);
        else
            printf("关系有点远,年长就叫老祖宗,同龄人就叫美女帅哥吧~\n");
    }
}

void addChild(BiTree& Tree)
{
    char name_get_child[20];
    Info new_Child;
    printf("请输入要为其添加孩子的人的名字:");
    scanf_s("%s", name_get_child, 20);
    BitNode* p = searchName(Tree, name_get_child);
    if (p == NULL)
    {
        printf("查无此人\n");
        return;
    }
    if (p->lc && p->rc)
        printf("此人已有两个孩子,添加失败!\n");
    else
    {
        printf("请输入孩子的姓名:");
        scanf_s("%s", new_Child.name, 20);
        printf("请输入孩子的出生日期:");
        scanf_s("%s", new_Child.birth, 10);
        printf("如果孩子结婚了,请输入1, 否则输入0:");
        int i;
        scanf_s("%d", &i);
        if (i != 1 && i != 0)
            printf("您输入了非法数字,系统将自动处理!\n");
        new_Child.wedding = i % 2;
        printf("请输入孩子的地址:");
        scanf_s("%s", new_Child.address, 20);
        printf("如果孩子健在,请输入1, 否则输入0:");
        scanf_s("%d", &i);
        if (i != 1 && i != 0)
            printf("您输入了非法数字,系统将自动处理!\n");
        new_Child.alive = i % 2;
        if (!i)
        {
            printf("请输入孩子的死亡时间:");
            scanf_s("%s", new_Child.death, 10);
        }
        else
            strcpy_s(new_Child.death, "null");
        if (p->lc)
            newLeft(p, new_Child);
        else
            newRight(p, new_Child);
        printf("添加成功!\n");
    }
}

void deletePerson(BiTree& Tree)
{
    char name_be_deleted[20];
    printf("请输入要删除的人的名字:");
    scanf_s("%s", name_be_deleted, 20);
    BitNode* p = searchName(Tree, name_be_deleted);
    if (p == NULL)
    {
        printf("查无此人\n");
        return;
    }
    if (p->lc || p->rc)
    {
        printf("请注意,此人的后代也将一并删除!\n确认删除吗?(Y/N)  ");
        char ch;
        scanf_s(" %c", &ch, 1);
        if (ch == 'N' || ch == 'n') return;
    }
    BitNode* f = findParent(Tree, p); // 判断是否为根结点
    if (f)
    {
        if (f->lc == p)
        {
            f->lc = NULL;
            delete p;
        }
        if (f->rc == p)
        {
            f->rc = NULL;
            delete p;
        }
    }
    else
        Tree = NULL;
    printf("删除成功!\n");
}

void updateInfo(BiTree Tree)
{
    char name_change[20];
    printf("请输入要修改信息的成员的姓名:");
    scanf_s("%s", name_change, 20);
    BitNode* p = searchName(Tree, name_change);
    if (p == NULL)
    {
        printf("查无此人\n");
        return;
    }
    char tmp[20];
    printf("请输入姓名,0为不修改:");
    scanf_s("%s", tmp, 20);
    if (tmp[0] != '0')
        strcpy_s(p->person.name, tmp);
    printf("请输入出生日期,no为不修改:");
    scanf_s("%s", tmp, 20);
    if (tmp[0] != 'n')
        strcpy_s(p->person.birth, tmp);
    printf("如果结婚了,请输入1, 否则输入0,输入-1则为不修改:");
    int i;
    scanf_s("%d", &i);
    if (i != -1)
    {
        if (i != 1 && i != 0)
            printf("您输入了非法数字,系统将自动处理!\n");
        p->person.wedding = i % 2;
    }
    printf("请输入地址,0为不修改:");
    scanf_s("%s", tmp, 20);
    if (tmp[0] != '0')
        strcpy_s(p->person.address, tmp);
    printf("如果健在,请输入1, 否则输入0,输入-1则为不修改:");
    scanf_s("%d", &i);
    if (i != -1)
    {
        if (i != 1 && i != 0)
            printf("您输入了非法数字,系统将自动处理!\n");
        p->person.alive = i % 2;
    }
    if (!i)
    {
        printf("请输入死亡时间,no为不修改:");
        scanf_s("%s", tmp, 20);
        if (tmp[0] != 'n')
            strcpy_s(p->person.death, tmp);
    }
    else
        strcpy_s(p->person.death, "null");
    /*BiTree L_result, R_result;
    if (strcmp(Tree->person.name, name_change) == 0)
        Tree = p;
    else
    {
        L_result = searchName(Tree->lc, name_change);
        R_result = searchName(Tree->rc, name_change);
        if (L_result)
            L_result = p;
        else
            R_result = p;
    }*/
    printf("更新成功!\n");
}

void transportBirth(BiTree BT, char bir[][20], int& i)
{
    if (BT)
    {
        strcpy_s(bir[i++], BT->person.birth);
        transportBirth(BT->lc, bir, i);
        transportBirth(BT->rc, bir, i);
    }
}

void sortBirthday(BiTree Tree, int n)
{
    char birth[20][20];
    transportBirth(Tree, birth, n);
    //printf("sfesfe %d\n", n);
    for (int i = 0; i < n - 1; i++)
        for (int j = i + 1; j < n; j++)
            if (strcmp(birth[i], birth[j]) > 0)
            {
                char tmp[20];
                strcpy_s(tmp, birth[i]);
                strcpy_s(birth[i], birth[j]);
                strcpy_s(birth[j], tmp);
            }
    outputTitle();
    for (int i = 0; i < n; i++)
    {
        //printf("%s\n", birth[i]);
        BitNode* p = findBirthday(Tree, birth[i]);
        //printf("%s\n", p->person.name);
        outputInfo(p);
    }
    printf("\n");
}


Main.cpp

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <Windows.h>
#include "generation.h"
using namespace std;

/*Info human[12] = { {"Havoc",'M',"19030611",1,"Moscow",0,"19800528"},
                   {"Jenny",'F',"19201120",1,"Washington",0,"19890416"},
                   {"Carville",'M',"19230526",1,"Paris",0,"19971231"},
                   {"Ivan",'M',"19440501",1,"Macau",0,"20080419"},
                   {"Tanya",'F',"19470811",0,"nefu",0,"20010501"},
                   {"Mary",'F',"19480505",1,"Tibet",0,"20070412"},
                   {"Jones",'M',"19490541",1,"London",0,"20161004"},
                   {"Mark",'M',"19601227",0,"Tokyo",1,"null"},
                   {"Lucy",'F',"19770324",0,"Jupyter",1,"null"},
                   {"Steven",'M',"19770519",1,"Mars",1,"null"},
                   {"Romanov",'M',"20000102",0,"M87",1,"null"},
                   {"Libra",'F',"20030518",0,"M87",1,"null"} };*/
char timeNow[27];
int wedding, alive;
bool flag = 0;
Info human[12];
//char name[20], sex, birth[10], address[20], deadth[10];

int calcDay(char *_day, int tag) // 计算当前日期为整数
{
    int today = 0, ten = 1;
    for (int i = tag-1; i >= tag-4; i--)
    {
        today += (_day[i] - '0') * ten;
        ten *= 10;
    }
    return today;
}

int fetchTime() // 处理读取到的时间
{
    char _month[4], _day[5];
    for (int i = 0; i < 3; i++)
    {
        _month[i] = timeNow[i + 4];
        //printf("%c", _month[i]);
    }
    _month[3] = '\0';
    //printf("%s\n", _month);
    for (int i = 0; i < 2; i++)
    {
        if (timeNow[i + 8] == ' ')
            _day[i + 2] = '0';
        else
            _day[i + 2] = timeNow[i + 8];
        //printf("%c", _day[i]);
    }
    _day[0] = '0';
    if (strcmp(_month, "Jan") == 0)
        _day[1] = '1';
    else if (strcmp(_month, "Feb") == 0)
        _day[1] = '2';
    else if (strcmp(_month, "Mar") == 0)
        _day[1] = '3';
    else if (strcmp(_month, "Apr") == 0)
        _day[1] = '4';
    else if (strcmp(_month, "May") == 0)
        _day[1] = '5';
    else if (strcmp(_month, "Jun") == 0)
        _day[1] = '6';
    else if (strcmp(_month, "Jul") == 0)
        _day[1] = '7';
    else if (strcmp(_month, "Aug") == 0)
        _day[1] = '8';
    else if (strcmp(_month, "Sep") == 0)
        _day[1] = '9';
    else 
    {
        _day[0] = '1';
        if (strcmp(_month, "Oct") == 0)
            _day[1] = '0';
        if (strcmp(_month, "Nov") == 0)
            _day[1] = '1';
        if (strcmp(_month, "Dec") == 0)
            _day[1] = '2';
    }
    _day[4] = '\0'; // 手持两把锟斤拷,口中疾呼烫烫烫
    //printf("%s\n", _day);
    return calcDay(_day, 4);
}

void printBirthday(BiTree Tree) // 显示当天生日的健在成员
{
    int dayTime = fetchTime();
    //printf("%d\n", dayTime);
    int n = 0, cnt = 0;
    char birth[20][20];
    transportBirth(Tree, birth, n);
    //printf("%d\n", n);
    for (int i = 0; i < n; i++)
    {
        int tmp = calcDay(birth[i], 8);
        //printf("%d %d\n", tmp, dayTime);
        if (!cnt && tmp == dayTime)
        {
            BitNode* p = findBirthday(Tree, birth[i]);
            if (p->person.alive)
            {
                printf("今天过生日的人是:%s ", p->person.name);
                cnt++;
            }
        }
        else if (tmp == dayTime)
        {
            BitNode* p = findBirthday(Tree, birth[i]);
            if (p->person.alive)
            {
                printf("%s ", p->person.name);
                cnt++;
            }
        }
    }
    if (!cnt)
        printf("今天没有过生日的人!");
    printf("\n");
}

void initMenu()
{
    printf("***--------------------------***\n");
    printf("* 1.从文件读取家族信息         *\n");
    printf("* 2.保存信息至文件             *\n");
    printf("| 3.显示家谱                   |\n");
    printf("| 4.显示第n代所有人的信息      |\n");
    printf("| 5.按照姓名查询,输出成员信息 |\n");
    printf("| 6.按照出生日期查询成员名单   |\n");
    printf("| 7.输入两人姓名,确定其关系   |\n");
    printf("| 8.某成员添加孩子             |\n");
    printf("| 9.删除某成员                 |\n");
    printf("| 10.修改某成员信息            |\n");
    printf("* 11.按出生日期对所有人排序    *\n");
    printf("* 12.重置所有信息              *\n");
    printf("* 13.退出系统                  *\n");
    printf("***--------------------------***\n");
}

int main()
{
    // 获取当前日期时间
    time_t now;
    time(&now);
    ctime_s(timeNow, sizeof timeNow, &now);
    printf("当前时间为:%s\n", timeNow);
    BiTree Tree = NULL;
    printf("****欢迎来到莫拉莱斯的家族管理系统!****\n");
    //printf("***--------------------------------***\n");
INIT:if (flag)
    {
        Tree = createTree(human);
        printBirthday(Tree);
    }
START:initMenu();
    printf("请输入要执行的操作:");
    int option;
    scanf_s("%d", &option);
    switch (option)
    {
    case 1:
        {
            ifstream fin("Generation.txt");
            for (int i = 0; i < 12; i++)
            {
                fin >> human[i].name >> human[i].sex >> human[i].birth >> wedding >> human[i].address >> alive >> human[i].death;
                human[i].wedding = wedding;
                human[i].alive = alive;
            }
            fin.close();
            printf("读取成功!\n");
            flag = 1;
            goto INIT;
            break;
        }
    case 2:
        {
            if (!flag)
            {
                MessageBox(NULL, TEXT("无数据可保存!"), TEXT("Warning"), MB_OK);
                goto START;
            }
            ofstream fout("Generation.txt");
            for (int i = 0; i < 12; i++)
                fout << human[i].name <<" " << human[i].sex << " " << human[i].birth << " " << human[i].wedding << " " << human[i].address << " " << human[i].alive << " " << human[i].death << endl;
            fout.close();
            printf("保存成功!\n");
            goto START;
            break;
        }
    case 13:
        MessageBox(NULL, TEXT("感谢您的使用!"), TEXT("即将退出"), MB_OK);
        exit(0);
    default:
    {
        if (!flag)
        {
            printf("请先读取文件!\n");
            MessageBox(NULL, TEXT("请先读取文件!"), TEXT("Warning"), MB_OK);
            goto START;
        }
        else
        {
            switch (option)
            {
            case 3:
                showFamily(Tree);
                goto START;
                break;
            case 4:
            {
                printf("请输入查询代数:");
                int n;
                scanf_s("%d", &n);
                if (n >= 1 && n <= 4)
                {
                    outputTitle();
                    showNGene(Tree, n);
                }
                else printf("输入有误!\n");
                goto START;
                break;
            }
            case 5:
                searchThreeGeneration(Tree);
                goto START;
                break;
            case 6:
                searchBirthday(Tree);
                goto START;
                break;
            case 7:
                judgeRelationship(Tree);
                goto START;
                break;
            case 8:
                addChild(Tree);
                goto START;
                break;
            case 9:
                deletePerson(Tree);
                goto START;
                break;
            case 10:
                updateInfo(Tree);
                goto START;
                break;
            case 11:
                sortBirthday(Tree, 0);
                goto START;
                break;
            case 12:
            {
                ifstream fin("Generation.bak");
                for (int i = 0; i < 12; i++)
                {
                    fin >> human[i].name >> human[i].sex >> human[i].birth >> wedding >> human[i].address >> alive >> human[i].death;
                    human[i].wedding = wedding;
                    human[i].alive = alive;
                }
                fin.close();
                ofstream fout("Generation.txt");
                for (int i = 0; i < 12; i++)
                    fout << human[i].name << " " << human[i].sex << " " << human[i].birth << " " << human[i].wedding << " " << human[i].address << " " << human[i].alive << " " << human[i].death << endl;
                fout.close();
                printf("重置成功!\n");
                goto INIT;
            }
            default:
                printf("输入有误,请重新输入!\n");
                MessageBox(NULL, TEXT("输入有误,请重新输入!"), TEXT("Warning"), MB_OK);
                goto START;
                break;
            }
        }
        break;
    }
    }
    //cout << "Hello World!\n";
    return 0;
}

效果图:
效果图3

四 图型结构

行车路线

小明和小芳出去乡村玩,小明负责开车,小芳来导航。
 小芳将可能的道路分为大道和小道。大道比较好走,每走1公里小明会增加1的疲劳度。小道不好走,如果连续走小道,小明的疲劳值会快速增加,连续走s公里小明会增加s2的疲劳度。
 例如:有5个路口,1号路口到2号路口为小道,2号路口到3号路口为小道,3号路口到4号路口为大道,4号路口到5号路口为小道,相邻路口之间的距离都是2公里。如果小明从1号路口到5号路口,则总疲劳值为(2+2)2+2+22=16+2+4=22。
 现在小芳拿到了地图,请帮助她规划一个开车的路线,使得按这个路线开车小明的疲劳度最小。

输入格式

输入的第一行包含两个整数n, m,分别表示路口的数量和道路的数量。路口由1至n编号,小明需要开车从1号路口到n号路口。
接下来m行描述道路,每行包含四个整数t, a, b, c,表示一条类型为t,连接a与b两个路口,长度为c公里的双向道路。其中t为0表示大道,t为1表示小道。保证1号路口和n号路口是连通的。

输出格式

输出一个整数,表示最优路线下小明的疲劳度。

样例输入

6 7
1 1 2 3
1 2 3 2
0 1 3 30
0 3 4 20
0 4 5 30
1 3 5 6
1 5 6 1

样例输出

76

样例说明

从1走小道到2,再走小道到3,疲劳度为52=25;然后从3走大道经过4到达5,疲劳度为20+30=50;最后从5走小道到6,疲劳度为1。总共为76。

数据规模和约定

对于30%的评测用例,1≤n≤8,1≤m≤10;
对于另外20%的评测用例,不存在小道;
对于另外20%的评测用例,所有的小道不相交;
对于所有评测用例,1≤n≤500,1≤m≤105,1≤a, b≤n,t是0或1,c≤105。保证答案不超过106。

//#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MaxV = 1010;
const ll inf = 0x7FFFFFFFFFFFFFFF;

typedef struct node{
    int v;
    long long dis;
    bool road; // 1-big 0-small
}car;

int n, m;
vector<car> Adj[MaxV];
long long D[MaxV], R[MaxV];
bool S[MaxV];

void Dijkstra(int v0)
{
    fill(D, D+MaxV, inf);
    D[v0] = 0;
    for(int i=0; i<n; i++)
    {
        int u = -1;
        long long minn = inf;
        for(int j=1; j<=n; j++)
            if(!S[j] && D[j]<minn)
            {
                u = j;
                minn = D[j];
            }
        if(u == -1) return;
        S[u] = 1;
        for(int j=0; j<Adj[u].size(); j++)
        {
            int v = Adj[u][j].v;
            long long dis = Adj[u][j].dis;
            bool flag = Adj[u][j].road;
            if(!S[v])
            {
                if(!flag && D[u]-R[u]*R[u]+(R[u]+dis)*(R[u]+dis)<D[v])
                {
                    D[v] = D[u]-R[u]*R[u]+(R[u]+dis)*(R[u]+dis);
                    R[v] = R[u]+dis;
                }
                if(flag && D[u]+dis<D[v])
                {
                    D[v] = D[u]+dis;
                    R[v] = 0;
                }
            }
        }
    }
}

int main()
{
    //ios::sync_with_stdio(false);
    cin>>n>>m;
    int t;
    for(int i=0; i<m; i++)
    {
        car t1, t2;
        cin>>t>>t2.v>>t1.v>>t1.dis;
        t2.dis = t1.dis;
        t1.road = t2.road = t^1;
        Adj[t1.v].push_back(t2);
        Adj[t2.v].push_back(t1);
    }
    Dijkstra(1);
    cout<<D[n]<<endl;
    return 0;
}

效果图:
效果图4

五 查找、排序、文件

二叉排序树

功能要求:
(1)从键盘输入一组学生记录建立二叉排序树;
(2)中序遍历二叉排序树;
(3)求二叉排序树深度;
(4)求二叉排序树的所有节点数和叶子节点数;
(5)向二叉排序树插入一条学生记录;
(6)从二叉排序树中删除一条学生记录;
(7)从二叉排序树中查询一条学生记录;
(8)以广义表的形式输出二叉排序树

//定义学生记录类型

Struct student 
{
  Char num[6];  //学号
  Int  grade;  //成绩
};

//定义二叉排序树节点值的类型为学生记录类型

typedef student  ElemType;

//定义二叉排序树的节点类型

typedef Struct BSTNode
{
  ElemType data;
  Struct BSTNode *left;
  Struct BSTNode *rchild;
} BSTNode;

binary.h

#pragma once
struct student {
	char num[10]; // 学号
	double grade; // 成绩
};
typedef student ElemType;
typedef struct BSTNode {
	ElemType data;
	struct BSTNode* lc, * rc;
}BSTNode, *BSTree;

void insertBST(BSTree& T, student elem); // 插入 - 5
void createBST(BSTree& T); // 创建 - 1
void inOrderTraverse(BSTree T); // 中序遍历 - 2
int calcDepth(BSTree T); // 计算深度 - 3
int cntLeaves(BSTree T); // 数叶子结点 - 4
int cntNodes(BSTree T); // 数结点 - 4
void deleteBST(BSTree& T, char* key); // 删除 - 6
double queryBST(BSTree T, char* name); // 查询成绩 - 7
void printBST(BSTree T); // 广义表 - 8

binary.cpp

#include "binary.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;

void insertBST(BSTree& T, student elem)
{
	if (!T)
	{
		BSTNode* s = new BSTNode;
		s->data = elem;
		s->lc = NULL;
		s->rc = NULL;
		T = s;
	}
	else if (strcmp(elem.num, T->data.num) < 0)
		insertBST(T->lc, elem);
	else if (strcmp(elem.num, T->data.num) > 0)
		insertBST(T->rc, elem);
}

void createBST(BSTree& T)
{
	T = NULL;
	int n;
	cout << "请输入学生人数:" << endl;
	cin >> n;
	cout << "请依次输入" << n << "个学生的成绩和学号:" << endl;
	while (n--)
	{
		student elem;
		cin >> elem.grade >> elem.num;
		insertBST(T, elem);
	}
	cout << "创建完成!" << endl;
}

void inOrderTraverse(BSTree T)
{
	if (T)
	{
		inOrderTraverse(T->lc);
		cout << "学号: " << T->data.num << "  " << "成绩: " << T->data.grade << endl;
		inOrderTraverse(T->rc);
	}
}

int calcDepth(BSTree T)
{
	int Ldepth, Rdepth;
	if (!T) return 0;
	else
	{
		Ldepth = calcDepth(T->lc);
		Rdepth = calcDepth(T->rc);
		if (Ldepth > Rdepth)
			return Ldepth + 1;
		else return Rdepth + 1;
	}
}

int cntLeaves(BSTree T)
{
	int cnt = 0;
	if (!T)
		return 0;
	else if (!T->lc && !T->rc)
		return 1;
	else
		return cntLeaves(T->lc) + cntLeaves(T->rc);
}

int cntNodes(BSTree T)
{
	if (!T)
		return 0;
	else
		return cntNodes(T->lc) + cntNodes(T->rc) + 1;
}

void deleteBST(BSTree& T, char* key)
{
	BSTNode* p = T, * f = NULL;
	while (p)
	{
		//cout << "p->data " << p->data.num << endl;
		if (!strcmp(p->data.num, key))
			break;
		f = p; // *f为*p的双亲结点
		if (strcmp(p->data.num, key) > 0)
			p = p->lc;
		else
			p = p->rc;
	}
	if (!p)
	{
		cout << "查无此人!" << endl;
		return;
	}
	/*---左右均不空,右空,左空---*/
	BSTNode* q = p;
	if (p->lc && p->rc)
	{
		BSTNode* s = p->lc;
		while (s->rc)
		{
			q = s;
			s = s->rc;
		}
		p->data = s->data;
		if (q != p)
			q->rc = s->lc;
		else
			q->lc = s->lc;
		delete s;
		cout << "删除成功!" << endl;
		return;
	}
	else if (!p->rc)
		p = p->lc;
	else if (!p->lc)
		p = p->rc;
	/*---将p所指的子树挂接到其双亲结点*f的相应位置---*/
	if (!f)
		T = p;
	else if (q == f->lc)
		f->lc = p;
	else
		f->rc = p;
	delete q;
	cout << "删除成功!" << endl;
	return;
}

double queryBST(BSTree T, char* num)
{
	if (!T) return -1;
	BSTNode* p = T;
	while (p)
	{
		if (!strcmp(p->data.num, num))
			return p->data.grade;
		else if (strcmp(p->data.num, num) > 0)
			p = p->lc;
		else if (strcmp(p->data.num, num) < 0)
			p = p->rc;
	}
	return -1;
}

void printBST(BSTree T)
{
	cout << T->data.num;
	if (T->lc)
	{
		cout << "(";
		printBST(T->lc);
		if (!T->rc)
			cout << ")";
	}
	if (T->rc)
	{
		cout << ",";
		if (!T->lc)
			cout << "(";
		printBST(T->rc);
		cout << ")";
	}
}

main.cpp

#include "binary.h"
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>

void menu()
{
    std::cout << "-------二叉排序树------" << std::endl;
    std::cout << "输入数字,执行相应操作:" << std::endl;
    std::cout << "1.从键盘读入以建立二叉排序树" << std::endl;
    std::cout << "2.中序遍历二叉排序树" << std::endl;
    std::cout << "3.求二叉排序树深度" << std::endl;
    std::cout << "4.求二叉排序树的所有节点数和叶子节点数" << std::endl;
    std::cout << "5.向二叉排序树插入一条学生记录" << std::endl;
    std::cout << "6.从二叉排序树中删除一条学生记录" << std::endl;
    std::cout << "7.从二叉排序树中查询一条学生记录" << std::endl;
    std::cout << "8.以广义表的形式输出二叉排序树" << std::endl;
    std::cout << "0.退出" << std::endl;
}

int main()
{
    BSTree T = NULL;
    int q;
    ElemType data;
    while (1)
    {
        menu();
        std::cin >> q;
        switch (q)
        {
        case 1:
            createBST(T);
            break;
        case 2:
            std::cout << "中序遍历结果为:" << std::endl;
            inOrderTraverse(T);
            break;
        case 3:
            std::cout << "树的深度为" << calcDepth(T) << std::endl;
            break;
        case 4:
            std::cout << "共有" << cntNodes(T) << "个结点," << cntLeaves(T) << "个叶子结点" << std::endl;
            break;
        case 5:
            std::cout << "请输入学号:";
            std::cin >> data.num;
            std::cout << "请输入成绩:";
            std::cin >> data.grade;
            insertBST(T, data);
            std::cout << "插入完成!" << std::endl;
            break;
        case 6:
            std::cout << "请输入学号:";
            std::cin >> data.num;
            deleteBST(T, data.num);
            break;
        case 7:
        {
            std::cout << "请输入学号:";
            std::cin >> data.num;
            double tmp = queryBST(T, data.num);
            if (tmp == -1) std::cout << "查无此人" << std::endl;
            else
                std::cout << "该生成绩为" << tmp << std::endl;
            break;
        }
        case 8:
            std::cout << "广义表形式为:";
            printBST(T);
            std::cout << std::endl;
            break;
        case 0:
            return 0;
        default:
            std::cout << "输入有误,请重新输入!" << std::endl;
            break;
        }
    }
    // std::cout << "Hello World!\n";
}

效果图:
在这里插入图片描述

完结。

https://gitee.com/morales/nefucurriculumdesign/tree/master/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84

  • 7
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值