数据结构实验

实验1:线性表

基本就是按照思路直接写

代码:
#include<iostream>
#include<fstream>
#include<cstring>
#include<iomanip>
using namespace std;

#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;		  //Status 是函数返回值类型,其值是函数结果状态代码。
                        //typedef int ElemType;   //ElemType 为可定义的数据类型,此设为int类型

#define MAXSIZE 100     //表可能达到的最大长度
typedef struct
{
    char no[8];          //8位学号
    char name[80];       //姓名
    int  grade;          //成绩
}Student;

//顺序表的定义(第一个程序用)
typedef  struct
{
    Student* elem;     //指向数据元素的基地址
    int  length;        //线性表的当前长度                                                           
}SqList;

//主函数,因为函数声明,故可放其他函数之前
int  main()
{
    SqList L;
    int i, choose;
    char name[80];

    //功能定义,声明函数
    Status  InitList(SqList & L);				//初使化顺序表
    Status  CreatList(SqList & L);				//构建顺序表
    Status  TraverseList(SqList L);				//显示
    Status  LocateElem(SqList L, char* name);	//查找
    Status  GetElem(SqList L, int i);			//获取
    Status  ListInsert(SqList & L, int i);		//插入
    Status  ListDelete(SqList & L, int i);		//删除
    int  ListLength(SqList L);				//顺序表长度
    Status  DestroyList(SqList & L);				//销毁顺序表

                                                //屏幕提示操作!
    cout << "---------------------\n";
    cout << "1. 初使化顺序表\n";
    cout << "2. 构建顺序表\n";
    cout << "3. 显示顺序表长度\n";
    cout << "4. 显示顺序表内容\n";
    cout << "5. 查找学生信息\n";
    cout << "6. 获取学生信息\n";
    cout << "7. 插入学生信息\n";
    cout << "8. 删除学生信息\n";
    cout << "9. 销毁顺序表\n";
    cout << "0. 退出\n\n";
    cout << "---------------------\n";

    choose = -1;
    while (choose != 0)
    {//函数调用
        cout << "请选择:";
        cin >> choose;
        switch (choose)
        {
        case 1://创建顺序表
            if (InitList(L))
                cout << "成功建立顺序表\n\n";
            else
                cout << "顺序表建立失败\n\n";
            break;
        case 2:   //构建顺序表
            if (CreatList(L))
                cout << "成功构建顺序表\n\n";
            else
                cout << "顺序表构建失败\n\n";
            break;
        case 3://顺序表长度
            cout << ListLength(L) << "\n\n";
            break;
        case 4://显示顺序表内容
            TraverseList(L);
            break;
        case 5://查找学生信息
            printf("请输入需要查找信息的学生姓名:\n");
            cin >> name;
            if (!LocateElem(L, name))
                cout << "查无此人\n\n";
            break;
        case 6: //获取学生信息
            printf("请输入需要获取信息的学生编号:\n");
            cin >> i;
            if (!GetElem(L, i))
                cout << "序号过大\n\n";
            break;
        case 7: //插入学生信息
            printf("请输入要插入学生的编号:\n");
            cin >> i;
            if (!ListInsert(L, i))
                cout << "序号太大插入失败\n\n";
            else
                cout << "插入成功\n\n";
            break;
        case 8://删除学生信息
            printf("请输入要删除学生的编号:\n");
            cin >> i;
            if (ListDelete(L, i))
                cout << "删除成功\n";
            else
                cout << "删除失败\n";
            break;
        case 9:  //销毁顺序表
            if (DestroyList(L)) cout << "成功删除顺序表\n\n";
            else   cout << "顺序表删除失败\n\n";
            break;
        }
        getchar();
    }
}

//1.初始化顺序表
Status  InitList(SqList& L)
{
    L.elem = new Student[MAXSIZE];
    if (!L.elem) exit(OVERFLOW);
    L.length = 0;
    return OK;
}

//2.创建顺序表
Status  CreatList(SqList& L)
{
    if (!L.elem)
        exit(OVERFLOW); //顺序表不存在退出
    do {
        printf("输入学号,姓名,成绩:\n");
        cin >> L.elem[L.length].no >> L.elem[L.length].name >> L.elem[L.length].grade;
        L.length++;
    } while (strcmp(L.elem[L.length - 1].name, "0") != 0);	//输入0 0 0时结束
    L.length--;
    if (L.length == 0)          //长度为0 初始时输入的no就是0 顺序表内无元素 创建失败
        return ERROR;
    return OK;
}

//3.遍历顺序表,显示顺序表内容
Status  TraverseList(SqList L)
{
    for (int i = 0;i < L.length;i++)
        cout << L.elem[i].no << ' ' << L.elem[i].name << ' ' << L.elem[i].grade << endl;
    cout << endl;
}

//4.查找(通过姓名)
Status  LocateElem(SqList L, char* name)
{
    for (int i = 0;i < L.length;i++)
        if (!strcmp(name, L.elem[i].name))
        {
            cout << L.elem[i].no << ' ' << L.elem[i].name << ' ' << L.elem[i].grade << endl << endl;
            return OK;
        }
    return ERROR;
}

//5.获取(通过序号)
Status  GetElem(SqList L, int i)
{
    if (i < L.length)
    {
        cout << L.elem[i].no << ' ' << L.elem[i].name << ' ' << L.elem[i].grade << endl << endl;
        return OK;
    }
    else
        return ERROR;
}

//6.插入(在指定位置i插入学生信息)
Status  ListInsert(SqList& L, int i)
{
    char no[8];
    char name[80];
    int grade;
    cin >> no >> name >> grade;
    if (0 <= i && i <= L.length)
    {
        for (int j = i + 1;j <= L.length;j++)
        {
            L.elem[j].grade = L.elem[j - 1].grade;
            strcpy(L.elem[j].name, L.elem[j - 1].name);
            strcpy(L.elem[j].no, L.elem[j - 1].no);
        }
        L.elem[i].grade = grade;
        strcpy(L.elem[i].name, name);
        strcpy(L.elem[i].no, no);
        L.length++;
        return OK;
    }
    else
        return false;
}

//7.删除(删除指定位置i的学生信息)
Status  ListDelete(SqList& L, int i)
{
    if (i >= 0 && i < L.length)
    {
        while (i < L.length - 1)
        {
            L.elem[i].grade = L.elem[i + 1].grade;
            strcpy(L.elem[i].name, L.elem[i + 1].name);
            strcpy(L.elem[i].no, L.elem[i + 1].no);
            i++;
        }
        L.length--;
        return OK;
        
    }
    else
        return ERROR;
}

//8.返回顺序表长度
int  ListLength(SqList L)
{
    return L.length;
}

//9. 销毁顺序表
Status  DestroyList(SqList& L)
{
    if (L.elem) delete[]L.elem;    //释放存储空间
    L.length = 0;
    return OK;
}

实验2 : 链表实现实验1

思路:

基本和实验1一样,只是加了文件读入。但是文件读入会莫名其妙读入错误数据,所以加了一个flag用来判断和使正常

代码:
#include<iostream>
#include<cstring>
#include<iomanip>
#include<fstream>

using namespace std;

#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;    //Status 是函数返回值类型,其值是函数结果状态代码。

typedef struct
{
    char no[80];		//学号
    char name[80];		//姓名
    int	 price;			//成绩
    
}Student;

typedef struct LNode
{
    Student data;		//结点的数据域
    struct LNode* next; //结点的指针域
} LNode, * LinkList;		//LinkList为指向结构体LNode的指针类型

typedef Student ElemType;  //ElemType 为可定义的数据类型,此设为Student类型
string head_1, head_2, head_3;//文件中的标题(第一行)
int  length;
bool flag = 0;
int main() {
    int a = 20;
    int i, choose, len;
    Student e;
    char name[80];
    LinkList L1 = NULL;
    //功能定义,声明函数

    Status InitList_L(LinkList & L);						//初使化链表
    void CreateList_H(LinkList & L, int n);					//前插法构建链表
    void CreateList_R(LinkList & L, int n);					//后插法构建链表
    int  ListLength_L(LinkList L);							//链表长度
    Status ListDisplay1(LinkList L);							//显示
    Status ListDisplay2(LinkList L);							//显示
    LNode* LocateElem_L(LinkList L, char* e);				//查找
    Status  GetElem_L(LinkList L, int i, Student & e);		//获取元素
    Status	ListInsert_L(LinkList & L, int i, Student & e);	//插入元素
    Status	ListDelete_L(LinkList & L, int i);				//删除
    Status  DestroyList_L(LinkList & L);						//销毁链表

    cout << "---------------------\n";
    cout << "1.初使化链表\n";
    cout << "2.前插法构建链表\n";
    cout << "3.后插法构建链表\n";
    cout << "4.求链表长度\n";
    cout << "5.显示链表内容\n";
    cout << "6.查找学生信息\n";
    cout << "7.获取学生信息\n";
    cout << "8.插入学生信息\n";
    cout << "9.删除学生信息\n";
    cout << "10.销毁链表\n";
    cout << "0.退出\n";
    cout << "---------------------\n";

    choose = -1;
    while (choose != 0)
    {
        cout << "\n\n请选择:";
        cin >> choose;
        switch (choose)
        {
        case 1: //初始化一个单链表
            if (InitList_L(L1))
                cout << "成功建立链表!\n";
            else
                cout << "建立链表失败!\n";
            break;

        case 2: //使用前插法创建单链表
            CreateList_H(L1, a);
            cout << "输入 students.txt 信息完毕(前插法)\n";
            break;

        case 3: //使用后插法创建单链表
            CreateList_R(L1, a);
            cout << "输入 students.txt 信息完毕(后插法)\n";
            break;

        case 4: //求单链表长度
            len = ListLength_L(L1);
            cout << "当前链表长度为:" << (flag ? len-2 : len-1) << "\n";
            break;

        case 5: //显示链表内容
            cout << "当前链表内容为:\n";
            if(flag){
            	ListDisplay1(L1);
			}else{
				ListDisplay2(L1);
			}
            break;

        case 6: //单链表的按序号取值
            cout << "请输入一个位置用来取值:";
            cin >> i;
            if (GetElem_L(L1, i, e))
            {
                cout << "查找成功\n";
                cout << "第" << i << "本学生证的信息是:\n";
                cout << e.no << "\t" << e.name << "\t" << e.price << endl;
                cout << endl;
            }
            else
                cout << "查找失败\n";
            break;

        case 7: //单链表的按值查找
            cout << "请输入所要查找学生姓名:";
            cin >> name;
            if (LocateElem_L(L1, name) != NULL)
            {
                e = LocateElem_L(L1, name)->data;
                cout << "查找成功\n";
                cout << "对应的学生信息为:\n" << e.no << "\t" << e.name << "\t" << e.price << "\n";
                cout << "补充语句" << endl;
            }
            else
                cout << "查找失败! " << name << " 没有找到\n";
            break;

        case 8: //单链表的插入
            cout << "请输入插入的位置和学生的信息(用空格隔开):";
            cin >> i;
            cin >> e.no >> e.name >> e.price;
            if (ListInsert_L(L1, i, e))	cout << "插入成功.\n";
            else	cout << "插入失败!\n";
            break;

        case 9: //单链表的删除
            cout << "请输入所要删除的学生的编号:";
            cin >> i;
            if (ListDelete_L(L1, i)) cout << "删除成功!\n";
            else	cout << "删除失败!\n";
            break;

        case 10: //销毁链表
            if (DestroyList_L(L1))
                cout << "成功销毁链表!\n";    break;
        }
    }
    return 0;
}
Status InitList_L(LinkList& L) { //构建
    L = new LNode; //生成新结点作为头结点,用头指针L指向头结点
    L->next = NULL; //头结点的指针域置空
    return OK;
}
void CreateList_H(LinkList& L, int n) {
    //逆位序输入 n 个元素的值,建立到头结点的单链表 L
    //补充语句
    LinkList p;
    L = new LNode;
    L->next = NULL; //先建立一个带头结点的空链表
    length = 0;
    fstream file; //定义文件指针 file
    file.open("date\\Student.txt"); //打开数据文件,Student.txt 必须放在与源程序同一文件夹下
    if (!file) { //判断文件是否存在
        cout << "未找到数据文件 Student.txt,无法打开!" << endl;
        exit(ERROR);
    }
    file >> head_1 >> head_2 >> head_3; //文件第一行:标题字符串
    char no0[80], name0[80];
    int price0;
    //	cout << head_1 << ' ' << head_2 << ' ' << head_3 << endl;
    while (file >> no0 >> name0 >> price0) { // 判断是否读完数据文件内容
        p = new LNode; //生成一个新结点,p 指向此结点
        //从文件中读入学生信息(学号、姓名和成绩)放入结点元素内
//        cout << no0 << ' ' << name0 << ' ' << price0 << endl;
        strcpy(p->data.no, no0); strcpy(p->data.name, name0);
        p->data.price = price0;
        p->next = L->next; //连接后结点(初始首元结点) L->next = p->next;
        L->next = p; //连接头结点(变成新的首元结点)
        length++; //同时对链表长度进行统计(长度加 1)}
    }
    file.close();
}
void CreateList_R(LinkList& L, int n) //后插法构建链表
{
    //补充语句
    L = new LNode;
    L->next = NULL; //先建立一个带头结点的空链表
    LinkList p, now = L;
    length = 0;
    flag = 1;
    fstream file; //定义文件指针 file
    file.open("date\\Student.txt"); //打开数据文件,Student.txt 必须放在与源程序同一文件夹下
    if (!file) { //判断文件是否存在
        cout << "未找到数据文件 Student.txt,无法打开!" << endl;
        exit(ERROR);
    }
    file >> head_1 >> head_2 >> head_3; //文件第一行:标题字符串
    while (!file.eof()) { // 判断是否读完数据文件内容
        p = new LNode; //生成一个新结点,p 指向此结点
        //从文件中读入学生信息(学号、姓名和成绩)放入结点元素内
        file >> p->data.no >> p->data.name >> p->data.price;
        p->next = NULL;
        now->next = p;
        now = p;
        length++; //同时对链表长度进行统计(长度加 1) }
    }
    file.close();
}
Status ListDisplay2(LinkList L)  //显示链表元素的内容
{
    LinkList p = L->next;
    for (int k = 1; k <= length; k++) {
        cout << p->data.no << '\t' << p->data.name << '\t' << p->data.price << endl;
        p = p->next;
    }
    return OK;
}
Status ListDisplay1(LinkList L)  //显示链表元素的内容
{
    LinkList p = L->next;
    for(int i = 1; i <= length-1; i++){
    	cout << p->data.no << '\t' << p->data.name << '\t' << p->data.price << endl;
        p = p->next;
	}
    return OK;
}

LNode* LocateElem_L(LinkList L, char* str) { //根据值(字串)查找
    LinkList p = L->next;
    while (p->next != NULL) {
        if (strcmp(p->data.name, str) == 0)
            return p;
        p = p->next;
    }
    return NULL;
}

Status GetElem_L(LinkList L, int i, Student& e) //根据序号查找
{
    LinkList p = L;
    if ((flag && i > length-1) || (!flag && i > length)) return ERROR;
    for (int j = 1; j <= i; j++)
        p = p->next;
    e = p->data;
    return OK;
}


Status ListInsert_L(LinkList& L, int i, Student& e) //插入一个结点 e 的内容
{
    LinkList p = L;
    if ((flag && i > length-1) || (!flag && i > length)) return ERROR;
    for (int j = 1; j <= i; j++) p = p->next;
    LinkList now = new LNode; now->data = e;
    now->next = p->next;
    p->next = now;
    length++;
    return OK;
}
Status ListDelete_L(LinkList& L, int i)  //删除
{
    if ((flag && i > length-1) || (!flag && i > length)) return ERROR;
    LinkList p = L;
    for (int j = 1; j <= i - 1; j++)  p = p->next;
    LinkList q = p->next;
    p->next = q->next;
    delete q; length--;
    return OK;
}
Status ListLength_L(LinkList L)//求链表长度
{
    int len = 0;
    while (L) {
        ++len;
        L = L->next;
    }
    return len;

}
Status DestroyList_L(LinkList& L) //销毁链表
{
    length = 0;
    LinkList p;
    while (L) {
        p = L;
        L = L->next;
        delete p;
    }
    return OK;
}


实验3:表达式求值

思路:

简单栈的模拟,遇到某个符号要做什么,写出来就行了。但是要注意的是输入的数不能超过9

代码:
#include<bits/stdc++.h>
using namespace std;

char op[1000];
int op_size = 0;
double num[1000];
int num_size = 0;


void solve(string s) {
	op_size = 0; num_size = 0;
	int k = 0;
	while (s[k] == '(') k++, op[op_size++] = '(';
	num[num_size++] = s[k] - '0'; 
	for (int i = k+1; i < s.size() - 1; i++) {
		if (s[i] >= '0' && s[i] <= '9') {
			double x = s[i] - '0';
			if (op[op_size - 1] == '*' || op[op_size - 1] == '/') {
				double y = num[num_size - 1]; num_size--;
				char ch = op[op_size - 1]; op_size--;
				num[num_size++] = (ch == '*' ? x * y : 1.0 * y / x);
			}
			else {
				if(op[op_size-1] == '-'){
					x = -x;
					op[op_size-1] = '+';
				}
				num[num_size++] = x;
			}
			continue;
		}
		if (s[i] == '(') {
			op[op_size++] = '(';
			continue;
		}
		if (s[i] == ')') {
			while (op_size >= 1 && op[op_size - 1] != '(') {
				char ch = op[op_size - 1]; op_size--;
				double num1 = num[num_size - 1];  num_size--;
				double num2 = num[num_size - 1];  num_size--;
				num[num_size++] = (ch == '+' ? num1 + num2 : num2 - num1);
			}
			op_size--;
			double x = num[num_size-1]; num_size--;
			while(op_size >= 1 && (op[op_size-1] == '*' || op[op_size-1] == '/')){
				double y = num[num_size-1]; num_size--;
				char ch = op[op_size-1]; op_size--;
				x = (ch == '*' ? y * x : y/x);
			}
			num[num_size++] = x;
			continue;
		}
		op[op_size++] = s[i]; 
	}
	double ans = num[num_size - 1]; num_size--;
	while (op_size >= 1 && num_size >= 1) {
		char ch = op[op_size - 1]; op_size--;
		double num1 = num[num_size - 1]; num_size--;
		ans = (ch == '+' ? num1 + ans : num1 - ans);
	}
	cout << "计算结果为: " << ans << endl;
}

int main() {
	while (1) {
		cout << "---------------------------------" << endl;
		cout << "0-9 以内的多项式计算" << endl;
		cout << "1.计算" << endl;
		cout << "0.退出\n" << endl;
		cout << "选择:";
		int choose;
		cin >> choose;
		switch(choose) {
		    case 1 : 
			{
				cout << "请输入要计算的表达式(操作数和结果都在 0-9 的范围内,以#结束):" << endl;
				string s; cin >> s;
				solve(s);
			};
			break;
			case 0 :
			{
				cout << "退出成功\n";
				return 0;
			};
		}
	}
}

实验四:字符串匹配

思路:

暴力匹配和kmp。一个是一个一个找,一个是用前缀和后缀相等优化下一次找的过程,省去不必要找的地方。

代码:
#include<iostream>
#include<cstring>
using namespace std;

#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
#define MAX_STR_LEN 255						// 用户可在 255(1 个字节)以内定义最大串长
typedef char SString[MAX_STR_LEN + 1];		// 0 号单元存放串的长度

Status StrAssign(SString T, char* chars);

int StrLength(SString T);

void StrPrint(SString T);

bool Concat(SString T, SString S1, SString S2);

int Index_BF(SString S, SString T, int pos);

void get_next(SString T, int next[]);

int Index_KMP(SString S, SString T, int pos, int next[]);

void get_nextval(SString T, int nextval[]);


int main()
{
	int i, * next;
	char ch1[80], ch2[80];
	SString S1, S2, S, SUB;					// 定义串,第一个单元存储串的长度
	cout << "请输入第一个字符串:";
	cin >> ch1;
	StrAssign(S1, ch1);
	StrPrint(S1);

	cout << "请输入第二个字符串:";
	cin >> ch2;
	StrAssign(S2, ch2);
	StrPrint(S2);
	cout << "------------------------------------------------\n";
	cout << "第一个字符串长度为: " << StrLength(S1) << endl;
	cout << "第二个字符串长度为: " << StrLength(S2) << endl;

	cout << "\n============连接两个字符串构造主串==============\n";
	Concat(S, S1, S2); //用 S 返回 S1 和 S2 联接而成的新串
	cout << "主串长度为: " << StrLength(S) << endl;
	cout << "主串为: ";
	StrPrint(S);
	cout << "请输入子串:";
	cin >> ch2;
	StrAssign(SUB, ch2);
	cout << "子串长度为: " << StrLength(SUB) << endl;

	cout << "\n---------------BF 匹配算法及实现----------------\n";
	i = Index_BF(S, SUB, 1);			// 利用算法 4.6 求得串 s2 在 s1 中首次匹配的位置 i
	if (i)
		printf("主串和子串在第%d 个字符处首次匹配\n", i);
	else
		printf("主串和子串匹配不成功\n");

	cout << "\n---------------KMP 匹配算法及实现---------------\n";
	next = new int[StrLength(SUB) + 1];
	get_next(SUB, next);			// 利用算法 4.7,求得 next 数组,存于 next 中
	printf("子串的 next 数组为: ");
	for (i = 1; i <= StrLength(SUB); i++)
		cout << *(next + i);
	printf("\n");
	i = Index_KMP(S, SUB, 1, next);		// 利用算法 4.6 求得串 s2 在 s1 中首次匹配的位置
	if (i)
		printf("主串和子串在第%d 个字符处首次匹配\n", i);
	else
		printf("主串和子串匹配不成功\n");

	cout << "\n--------------KMP改进匹配算法及实现-------------\n";
	get_nextval(SUB, next);			    		// 利用算法 4.8,求得 next 数组,存于 next 中
	printf("子串的 nextval 数组为: ");
	for (i = 1; i <= StrLength(SUB); i++)
		cout << *(next + i);
	printf("\n");
	i = Index_KMP(S, SUB, 1, next);		// 利用算法 4.6 求得串 s2 在 s1 中首次匹配的位置 i
	if (i)
		printf("主串和子串在第%d 个字符处首次匹配\n", i);
	else
		printf("主串和子串匹配不成功\n");

	getchar();
	return 0;
}


Status StrAssign(SString T, char* chars) { //生成一个其值等于chars的串T
	int i;
	if (strlen(chars) > MAX_STR_LEN)
		return ERROR;
	else {
		T[0] = strlen(chars);				//第1个单元存放串的长度
		for (i = 1; i <= T[0]; i++)
			T[i] = chars[i - 1];
		return OK;
	}
}


void StrPrint(SString T)
{
	int i;
	for (i = 1; i <= T[0]; i++)
		cout << T[i];
	printf("\n");
}

int StrLength(SString T)
{
	return  T[0];
}


//用T返回S1和S2联接而成的新串,若未截断,则返回TRUE,否则返回FALSE
bool Concat(SString T, SString S1, SString S2)
{
	int t = 0;
	if (S1[0] + S2[0] <= MAX_STR_LEN)
	{ // 未截断
		for (int i = 1; i <= S1[0]; i++)
			T[++t] = S1[i];
		for (int i = 1; i <= S2[0]; i++)
			T[++t] = S2[i];
		T[0] = S1[0] + S2[0];
		return true;
	}
	else
	{ // 截断 S2
		for (int i = 1; i <= S1[0]; i++)
			T[t++] = S1[i];
		for (int i = 1; i <= MAX_STR_LEN - S1[0]; i++)
			T[t++] = S2[i];
		T[0] = MAX_STR_LEN;
		return false;
	}
}

//算法4.1 BF算法
int Index_BF(SString S, SString T, int pos)
{
	//返回模式T在主串S中第pos个字符之后第s一次出现的位置。若不存在,则返回值为0
	//其中,T非空,1≤pos≤StrLength(S)
	int i = pos;
	int j = 1;
	while (i <= S[0] && j <= T[0])
	{
		if (S[i] == T[j])
		{
			i++;
			j++;
		} //继续比较后继字符
		else
		{
			i = i - j + 2;
			j = 1;
		} //指针后退重新开始匹配
		if (j > T[0])
			return i - j + 1;
	}
	return 0;
}//Index


//算法4.3 计算next函数值
void get_next(SString T, int next[])
{ //求模式串T的next函数值并存入数组next
	int i = 1, j = 0;
	next[1] = 0;
	while (i < T[0])
		if (j == 0 || T[i] == T[j])
		{
			i++;
			j++;
			next[i] = j;
		}
		else
			j = next[j];
}//get_next

//算法4.2 KMP算法
int Index_KMP(SString S, SString T, int pos, int next[])
{ 	// 利用模式串T的next函数求T在主串S中第pos个字符之后的位置的KMP算法
	//其中,T非空,1≤pos≤StrLength(S)
	int i = pos, j = 1;
	while (i <= S[0] && j <= T[0])
	{
		if (S[i] == T[j] || j == 0)		// 继续比较后继字
		{
			i++;
			j++;
		}
		else
			j = next[j];				// 模式串向右移动
	}
	if (j > T[0])						// 匹配成功
		return i - j + 1;
	else
		return 0;
}//Index_KMP

//算法4.4 计算next函数修正值
void get_nextval(SString T, int nextval[])
{ // 求模式串T的next函数修正值并存入数组nextval
	int i = 1, j = 0;
	nextval[1] = 0;
	while (i < T[0])
		if (j == 0 || T[i] == T[j])
		{
			i++;
			j++;
			if (T[i] != T[j])
				nextval[i] = j;
			else
				nextval[i] = nextval[j];
		}
		else
			j = nextval[j];
}//get_nextval

实验5.二叉树

思路:

简单找就好

代码:
// 5.BiTree.cpp : 定义控制台应用程序的入口点。
//
/***********************二叉树综合运算******************************/
#include<iostream>
using namespace std;
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
typedef int Status;		// Status是函数的类型
typedef char TElemType;

//二叉链表定义
typedef struct BiNode {
	char data;
	struct BiNode* lchild, * rchild;
} BiTNode, * BiTree;

typedef BiTree QElemType;

//链队列的定义
typedef struct QNode {
	QElemType data;
	QNode* next;
}*QueuePtr;

typedef struct {
	QueuePtr front, rear; // 队头、队尾指针
} LinkQueue;


/***************以下为队列常用运算函数***************/
//初始化队列
Status InitQueue(LinkQueue& Q) {
	// 构造一个空队列Q
	Q.front = Q.rear = new QNode;
	Q.front->next = NULL;
	return OK;
}
//入队 算法3.17
Status EnQueue(LinkQueue& Q, QElemType e) {
	// 插入元素e为Q的新的队尾元素
	QNode* p = new QNode;
	p->data = e;
	p->next = NULL;
	Q.rear->next = p;  //将新结点插入队尾
	Q.rear = p;		   //修改队尾指针
	return OK;
}
//判断队空
Status QueueEmpty(LinkQueue Q) {
	// 若Q为空队列,则返回TRUE,否则返回FALSE
	if (Q.front->next == NULL)
		return TRUE;
	else
		return FALSE;
}
//出队
Status DeQueue(LinkQueue& Q, QElemType& e) {
	// 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR
	if (Q.front == Q.rear)
		return ERROR;
	QNode* p = Q.front->next;   //p指向队头指针
	e = p->data;
	Q.front->next = p->next;	//修改头指针
	if (Q.rear == p)
		Q.rear = Q.front;       //最后一个元素被删,队尾指针指向头结点
	delete p;
	return OK;
}

/***************以下为二叉树综合运算函数***************/
void InitBiTree(BiTree& T) {
	// 操作结果:构造空二叉树T
	T = NULL;
}

Status BiTreeEmpty(BiTree T) {
	// 初始条件:二叉树T存在。操作结果:若T为空二叉树,则返回TRUE,否则FALSE
	if (T)
		return FALSE;
	else
		return TRUE;
}

//销毁二叉树
void DestroyBiTree(BiTree T) {
	// 初始条件:二叉树T存在。操作结果:销毁二叉树T
	if (T) { // 非空树
		if (T->lchild) // 有左孩子
			DestroyBiTree(T->lchild); // 销毁左孩子子树
		if (T->rchild) // 有右孩子
			DestroyBiTree(T->rchild); // 销毁右孩子子树
		free(T); // 释放根结点
		T = NULL; // 空指针赋0
	}
}

//把指针指向给定元素
BiTree Point(BiTree T, TElemType s) {               //BFS
	// 返回二叉树T中指向元素值为s的结点的指针。另加
	LinkQueue q;
	BiTree a;
	if (T) { // 非空树
		InitQueue(q);  // 初始化队列
		EnQueue(q, T); // 根指针入队
		while (!QueueEmpty(q)) { // 队不空
			DeQueue(q, a); // 出队,队列元素赋给a
			if (a->data == s)
				return a;
			if (a->lchild) // 有左孩子
				EnQueue(q, a->lchild); // 入队左孩子
			if (a->rchild) // 有右孩子
				EnQueue(q, a->rchild); // 入队右孩子
		}
	}
	//  cout<<a->data<<endl;
	return NULL;
}

//给指定结点赋值
void Assign(BiTree p, TElemType value) {
	// 给p所指结点赋值为value
	p->data = value;
}
求某结果左孩子的值,如无则返回空
TElemType LeftChild(BiTree T, TElemType e) {
	// 初始条件:二叉树T存在,e是T中某个结点。操作结果:返回e的左孩子。若e无左孩子,则返回"空"
	BiTree a;
	if (T) { // 非空树
		a = Point(T, e);		// a是结点e的指针
		if (a && a->lchild)		// T中存在结点e且e存在左孩子
			return  a->lchild->data;	// 返回e的左孩子的值
	}
	return ' '; // 其余情况返回空
}

求某结果右孩子的值,如无则返回空
TElemType RightChild(BiTree T, TElemType e) {
	// 初始条件:二叉树T存在,e是T中某个结点。操作结果:返回e的右孩子。若e无右孩子,则返回"空"
	BiTree a;
	if (T) { // 非空树
		a = Point(T, e);		// a是结点e的指针
		if (a && a->rchild)		// T中存在结点e且e存在右孩子
			return a->rchild->data; // 返回e的右孩子的值
	}
	return ' '; // 其余情况返回空
}


利用队列求取某结点双亲的值,如找不能,则返回空
TElemType Parent(BiTree T, TElemType e) {               //BFS
	// 初始条件:二叉树T存在,e是T中某个结点
	// 操作结果:若e是T的非根结点,则返回它的双亲,否则返回"空"
	LinkQueue q;
	QElemType a; //BiTree a;
	if (T) { // 非空树
		InitQueue(q); // 初始化队列
		EnQueue(q, T);  // 树根指针入队
		while (!QueueEmpty(q)) { // 队不空
			DeQueue(q, a); // 出队,队列元素赋给a
			if (a->lchild && a->lchild->data == e || a->rchild && a->rchild->data == e) // 找到e(是其左或右孩子)
				return   a->data;  //返回e的双亲的值
			else { // 没找到e,则入队其左右孩子指针(如果非空)
				if (a->lchild)
					EnQueue(q, a->lchild);
				if (a->rchild)
					EnQueue(q, a->rchild);
			}
		}
	}
	return ' '; // 树空或没找到e
}

用算法5.3 先序遍历的顺序建立二叉链表
void  CreateBiTree(BiTree& T) {
	//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
	char ch;
	cin >> ch;
	if (ch == '#')  T = NULL;	//递归结束,建空树
	else {
		T = new BiTNode;
		T->data = ch;
		CreateBiTree(T->lchild);
		CreateBiTree(T->rchild);
	}
}
用算法5.1 中序遍历
void InOrderTraverse(BiTree T) {
	//中序遍历二叉树T的递归算法
	if (T) {
		InOrderTraverse(T->lchild);
		cout << T->data << ' ';
		InOrderTraverse(T->rchild);
	}
}
先序遍历
void PreOrderTraverse(BiTree T) {
	//先序遍历二叉树T的递归算法
	if (T) {
		cout << T->data << ' ';
		PreOrderTraverse(T->lchild);
		PreOrderTraverse(T->rchild);
	}
}
后序遍历
void PostOrderTraverse(BiTree T) {
	//后序遍历二叉树T的递归算法
	if (T) {
		PostOrderTraverse(T->lchild);
		PostOrderTraverse(T->rchild);
		cout << T->data << ' ';
	}
}

//求树深度
int BiTreeDepth(BiTree T) {
	int m, n, depth;
	if (T == NULL) return 0; //如果是空树,深度为0,递归结束
	else {
		m = BiTreeDepth(T->lchild);
		n = BiTreeDepth(T->rchild);
		depth = max(m, n) + 1;
	}
	return depth;
}
//求叶子数 /
int LeafCount(BiTree T) {
	if (T == NULL)
		return 0;    //如果是空树,返回0
	if (T->lchild == NULL && T->rchild == NULL)
		return 1;    //如果是叶子结点,返回1
	else
		return LeafCount(T->lchild) + LeafCount(T->rchild);
}
求结点数/
int NodeCount(BiTree T) {
	if (T == NULL)
		return 0;
	else
		return NodeCount(T->lchild) + NodeCount(T->rchild) + 1;
}
求根结点值//
TElemType Root(BiTree T) {
	if (T)
		return T->data;
	else return ' ';
}

int main() {
	BiTree T, p;
	TElemType e1, e2;
	int islelect;

	InitBiTree(T);
	cout << "------------------------------------------------------\n";
	printf("构造空二叉树后,树空否?%d(1:是 0:否)树的深度=%d\n", BiTreeEmpty(T), BiTreeDepth(T));
	e1 = Root(T);
	if (e1 != ' ')
		printf("二叉树的根为: %c\n", e1);
	else
		printf("树空,无根\n");
	cout << "------------------------------------------------------\n";

	printf("请先序输入二叉树(P121图5.10(b): ABC##DE#G##F###)\n");
	CreateBiTree(T);
	printf("建立二叉树后,树空否?%d(1:是 0:否)", BiTreeEmpty(T));

	e1 = Root(T);
	if (e1 != ' ')
		printf("二叉树的根为: %c\n", e1);
	else
		printf("树空,无根\n");
	cout << "------------------------------------------------------\n";
	cout << " 树的叶子数=" << LeafCount(T) << endl;
	cout << " 树的结点数=" << NodeCount(T) << endl;
	cout << " 树的叶深度=" << BiTreeDepth(T) << endl;

	printf("\n先序递归遍历二叉树:\n");
	PreOrderTraverse(T);
	printf("\n中序递归遍历二叉树:\n");
	InOrderTraverse(T);
	printf("\n后序递归遍历二叉树:\n");
	PostOrderTraverse(T);
	cout << "\n------------------------------------------------------\n";

	printf("\n请输入一个结点的值: ");
	cin >> e1;
	// cout<<e1;
	p = Point(T, e1); // p为e1的指针
	if (p)
		printf("结点的值为%c\n", p->data);
	else {
		cout << "输入结点值错误!请重新输入\n";
		cin >> e1;
		p = Point(T, e1);
		while(!p) {
			cout << "输入结点值错误!请重新输入\n";
			cin >> e1;
			p = Point(T, e1);
		}
	}
	cout << "\n------------------------------------------------------\n";

	printf("欲改变此结点的值,请输入新值: ");
	cin >> e2;
	Assign(p, e2);
	printf("\n先序递归遍历二叉树:");
	PreOrderTraverse(T);

	e1 = Parent(T, e2);
	if (e1 != ' ')
		printf("\n%c的双亲是%c", e2, e1);
	else
		printf("\n%c没有双亲\n", e2);

	e1 = LeftChild(T, e2);
	if (e1 != ' ')
		printf("\n%c的左孩子是%c\n", e2, e1);
	else
		printf("\n%c没有左孩子\n", e2);

	e1 = RightChild(T, e2);
	if (e1 != ' ')
		printf("\n%c的右孩子是%c\n", e2, e1);
	else
		printf("\n%c没有右孩子\n", e2);

	DestroyBiTree(T);
	return 0;
}


实验6:赫夫曼树

思路:

简单来说就是我们每次找两个最小的,然后一直维护就好

代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int b[N];
map<int, string> mp;
struct vv {
	int w, id = 0;
	vv *date;
	vv* pa, * l, * r;
	bool operator<(const vv f)const { return f.w < w; }
	vv() {
		date = nullptr;
		pa = nullptr;
		l = nullptr;
		r = nullptr;
	} 
};
int n;
vv* root;

void build() {
	vv* node;
	priority_queue<vv> q;
	for (int i = 1; i <= n; i++) {
		node = new vv;
		cin >> node->w;
		b[i] = node->w;
		node->date = node;
		node->id = i;
		q.push(*node);
	}
	while (q.size() != 1) {
		node = new vv;
		auto x1 = q.top(); q.pop();
		auto x2 = q.top(); q.pop();
		node->w = x1.w + x2.w;
		node->l = x1.date, node->r = x2.date;
		(x1.date)->pa = node; 
		(x2.date)->pa = node;
		node->date = node;
		q.push(*node);
	}
	auto now = q.top(); q.pop();
	root = now.date;
}

void dfs(vv* to, string s) {
	if (to->l) dfs(to->l, s+'0');
	if (to->r) dfs(to->r, s+'1');
	if (!(to->l) && !(to->r)){
		mp[to->id] = s;
	}
}

int main() {
	cout << "输入叶子数" << endl; 
	cin >> n;
	cout << "输入叶子内容" << endl;
	build();
	dfs(root, "");
	for(int i = 1; i <= n; i++){
		cout << b[i] << ": " << mp[i] << endl;
	}
}

实验7.1邻接矩阵

代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int G[N][N];
bool vis[N];
int n, m;

//队列 
struct que{
	int quee[1000];
	int pre = 0, end = 0;
}; 

void push(que &x, int y){
	if(x.pre == 0){
		x.quee[++(x.pre)] = y;
	}
	x.quee[++(x.end)] = y;
}
void pop(que &x){
	x.pre++;
}
bool empty(que &x){
	if(x.pre > x.end) return 1;
	return 0;
}
int top(que &x){
	return x.quee[x.pre];
} 


void add(int u, int v, int w) {
	G[u][v] = G[v][u] = min(G[v][u], w);
}

void init(){
	for(int i = 1; i <= 100; i++){
		for(int j = 1; j <= 100; j++){
			G[i][j] = 10000;
		}
	}
}

//深度优先搜索
void dfs(int F[][110], int x) {
//	if(x > n) return;
	
	cout << x << ' ';
	vis[x] = 1;
	for (int i = 1; i <= n; i++) {
		if (F[x][i] != 10000 && !vis[i]) {
			vis[i] = 1;
			dfs(F, i);
		}
	}
}
//广度优先搜索
void bfs(int F[][110], int x){
	que q;
	push(q, x); 
	cout << x << ' ';
	vis[x] = 1;
	while(!empty(q)){
		int now = top(q); pop(q);
		for(int i = 1; i <= n; i++){
			if(F[now][i] != 10000 && !vis[i]){
				cout << i << ' ';
				vis[i] = 1;
				push(q, i);
			}
		}
	}
}


int main() {
	
	init();
	
	freopen("C:\\freopen\\input.txt", "r", stdin);
	cout << "输入点的个数,边的个数" << endl;
	cin >> n >> m;
	cout << n << ' ' << m << endl;
	for (int i = 1, u, v, w; i <= m; i++) {
		cout << "输入边的连接关系 u-(w)->v(表示u到v有一条为w的路径)\n";
		cin >> u >> v >> w;
		cout << u << ' ' << v << ' ' << w << endl;
		add(u, v, w);
	}
	int pos = 1;
	cout << "请输入起点 : ";
	cin >> pos;
	cout << pos << endl;
	cout << "\n深度优先搜索的结果是 " <<  endl;
	dfs(G, pos);
	memset(vis, 0, sizeof(vis));
	cout << "\n广度优先搜索的结果是 " << endl;
	bfs(G, pos);
}

实验7.2 邻接表

代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 110;
bool vis[N];
//存图---------------------- 
struct node{
	int to, w;
	node *next = nullptr;
	node(){
		next = NULL;
	}
};
node head[N], *t;
void add(int from, int to, int w){
	t = new node();
	t->to = to;
	t->w = w;
	t->next = head[from].next;
	head[from].next = t;
}
//----------------------------
//队列---------------------
struct que{
	node quee[1010];
	int pre = 0, end = 0;
};
void push(que &x, node y){
	if(x.pre == 0){
		x.quee[++(x.pre)] = y;
	}
	x.quee[++(x.end)] = y;
}
void pop(que &x){
	x.pre++;
}
bool empty(que &x){
	if(x.pre > x.end) return 1;
	return 0;
}
node top(que &x){
	return x.quee[x.pre];
} 
//--------------

int n, m;

void dfs(int pos){
	cout << pos << ' ';
	vis[pos] = 1;
	for(node *now = head[pos].next; now != NULL; now = now->next){
		if(!vis[now->to]){
			vis[now->to] = 1;
			dfs(now->to);
		}
	}
}

void bfs(int pos){
	cout << pos << ' ';
	node tm = head[pos];
	que q;
	push(q, tm);
	vis[pos] = 1;
	while(!empty(q)){
		node now = top(q); pop(q);
		int to = now.to;
		node e = *(now.next);
		for(; e.next != NULL; e = *(e.next)){
			if(!vis[e.to]){
				vis[e.to] = 1;
				cout << e.to << ' ';
				push(q, head[e.to]);
			}
		}
		if(!vis[e.to]){
			if(!vis[e.to]){
				vis[e.to] = 1;
				cout << e.to << ' ';
				push(q, head[e.to]);
			}
		}
	}
}


int main(){
//	init();
	cout << "202013160226 李发展" << endl;
	cout << "请输入点的个数,边的个数" << endl; 
	cin >> n >> m;
	cout << n << ' ' << m << endl;
	for(int i = 1, u,v,w; i <= m; i++){
		cout << "输入边的连接关系 u-(w)->v(表示u到v有一条为w的路径)\n";
		cin >> u >> v >> w;
		cout << u << ' ' << v << ' ' << w << endl;
		add(u,v,w);
		add(v,u,w);
	}
	int pos;
	cout << "请输入起点 : ";
	cin >> pos;
	cout<< "\n深度优先搜索的结果是 : " << endl;
	dfs(pos);
	memset(vis, 0, sizeof(vis));
	cout << "\n广度优先搜索的结果是 : " << endl;
	bfs(pos);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值