算法训练营入门 代码 自用

5.3  二叉树遍历

traverse

#include 
#include //引入队列头文件
using namespace std;

typedef struct Bnode	/*定义二叉树存储结构*/
{ char data;
  struct Bnode *lchild,*rchild;
}Bnode,*Btree;

void Createtree(Btree &T)	/*创建二叉树函数*/
{
    //按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
	char ch;
	cin >> ch;
	if(ch=='#')
        T=NULL;			//递归结束,建空树
	else{
		T=new Bnode;
		T->data=ch;					//生成根结点
		Createtree(T->lchild);	//递归创建左子树
		Createtree(T->rchild);	//递归创建右子树
	}
}

void preorder(Btree T)//先序遍历
{
    if(T)
    {
       cout<data<<"  ";
       preorder(T->lchild);
       preorder(T->rchild);
    }
}

void inorder(Btree T)//中序遍历
{
    if(T)
    {
       inorder(T->lchild);
       cout<data<<"  ";
       inorder(T->rchild);
    }
}

void posorder(Btree T)//后序遍历
{
    if(T)
    {
       posorder(T->lchild);
       posorder(T->rchild);
       cout<data<<"  ";
    }
}

bool Leveltraverse(Btree T)
{
    Btree p;
    if(!T)
        return false;
    queueQ; //创建一个普通队列(先进先出),里面存放指针类型
    Q.push(T); //根指针入队
    while(!Q.empty()) //如果队列不空
    {
        p=Q.front();//取出队头元素作为当前扩展结点livenode
        Q.pop(); //队头元素出队
        cout<data<<"  ";
        if(p->lchild)
            Q.push(p->lchild); //左孩子指针入队
        if(p->rchild)
            Q.push(p->rchild); //右孩子指针入队
    }
    return true;
}

int main()
{
    Btree mytree;
    cout<<"按先序次序输入二叉树中结点的值(孩子为空时输入#),创建一棵二叉树"<

depth 

#include 
using namespace std;

typedef struct Bnode	/*定义二叉树存储结构*/
{ char data;
  struct Bnode *lchild,*rchild;
}Bnode,*Btree;

void Createtree(Btree &T)	/*创建二叉树函数*/
{
    //按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
	char ch;
	cin >> ch;
	if(ch=='#')
        T=NULL;			//递归结束,建空树
	else{
		T=new Bnode;
		T->data=ch;					//生成根结点
		Createtree(T->lchild);	//递归创建左子树
		Createtree(T->rchild);	//递归创建右子树
	}
}

int Depth(Btree T)//求二叉树的深度
{
    int m,n;
    if(T==NULL)//如果为空树,深度为0
        return 0;
    else
    {
       m=Depth(T->lchild);//递归计算左子树深度
       n=Depth(T->rchild);//递归计算左子树深度
       if(m>n)
          return m+1;//返回左右子树最大值加1
       else
          return n+1;
    }
}

int main()
{
    Btree mytree;
    cout<<"按先序次序输入二叉树中结点的值(孩子为空时输入#),创建一棵二叉树"<

leaf 

#include 
using namespace std;

typedef struct Bnode	/*定义二叉树存储结构*/
{ char data;
  struct Bnode *lchild,*rchild;
}Bnode,*Btree;

void Createtree(Btree &T)	/*创建二叉树函数*/
{
    //按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
	char ch;
	cin >> ch;
	if(ch=='#')
        T=NULL;			//递归结束,建空树
	else{
		T=new Bnode;
		T->data=ch;					//生成根结点
		Createtree(T->lchild);	//递归创建左子树
		Createtree(T->rchild);	//递归创建右子树
	}
}

int LeafCount(Btree T)//求二叉树的叶子数
{
    if(T==NULL)//如果为空树,深度为0
        return 0;
    else
        if(T->lchild==NULL&&T->rchild==NULL)//左右子树均为空,则叶子数为1
           return 1;
        else
           return LeafCount(T->lchild)+LeafCount(T->rchild);//递归计算左子树和右子树的叶子数之和
}

int NodeCount(Btree T)//求二叉树的结点数
{
    if(T==NULL)//如果为空树,深度为0
        return 0;
    else
        return NodeCount(T->lchild)+NodeCount(T->rchild)+1;//递归计算左子树和右子树的结点数之和加1
}

int main()
{
    Btree mytree;
    cout<<"按先序次序输入二叉树中结点的值(孩子为空时输入#),创建一棵二叉树"<

PreinCreateBitree 

#include 
using namespace std;
typedef struct node
{
    char data;
    struct node *lchild,*rchild;
}BiTNode,*BiTree;

BiTree pre_mid_createBiTree(char *pre,char *mid,int len) //前序中序还原建立二叉树
{
    if(len==0)
        return NULL;
    char ch=pre[0];  //找到先序中的第一个结点
    int index=0;
    while(mid[index]!=ch)//在中序中找到的根结点的左边为该结点的左子树,右边为右子树
    {
        index++;
    }
    BiTree T=new BiTNode;//创建根结点
    T->data=ch;
    T->lchild=pre_mid_createBiTree(pre+1,mid,index);//建立左子树
    T->rchild=pre_mid_createBiTree(pre+index+1,mid+index+1,len-index-1);//建立右子树
    return T;
}

BiTree pro_mid_createBiTree(char *last,char *mid,int len)//后序中序还原建立二叉树
{
    if(len==0)
       return NULL;
    char ch=last[len-1]; //取得后序遍历顺序中最后一个结点
    int index=0;//在中序序列中找根结点,并用index记录长度
    while(mid[index]!=ch)//在中序中找到根结点,左边为该结点的左子树,右边为右子树
       index++;
    BiTree T=new BiTNode;//创建根结点
    T->data=ch;
    T->lchild=pro_mid_createBiTree(last,mid,index);//建立左子树
    T->rchild=pro_mid_createBiTree(last+index,mid+index+1,len-index-1);//建立右子树
    return T;
}

void pre_order(BiTree T)//前序递归遍历二叉树
{
    if(T)
    {
        cout<data;
        pre_order(T->lchild);
        pre_order(T->rchild);
    }
}

void pro_order(BiTree T)//后序递归遍历二叉树
{
    if(T)
    {
        pro_order(T->lchild);
        pro_order(T->rchild);
        cout<data;
    }
}
int main()
{
    BiTree T;
    int n;
    char pre[100],mid[100],last[100];
    cout<<"1. 前序中序还原二叉树\n";
	cout<<"2. 后序中序还原二叉树\n";
	cout<<"0. 退出\n";
	int choose=-1;
	while(choose!=0)
	{
	    cout<<"请选择:";
		cin>>choose;

		switch (choose)
		{
		    case 1://前序中序还原二叉树
		        cout<<"请输入结点的个数:"<>n;
		        cout<<"请输入前序序列:"<>pre[i];
                cout<<"请输入中序序列:"<>mid[i];
                T=pre_mid_createBiTree(pre,mid,n);
                cout<>n;
                cout<<"请输入后序序列:"<>last[i];
                cout<<"请输入中序序列:"<>mid[i];
                T=pro_mid_createBiTree(last,mid,n);
                cout<

 

6.图

6.1 图的存储1 创建无向图的邻接矩阵

#include//创建无向图的邻接矩阵
using namespace std;
#define MaxVnum 100  //顶点数最大值
typedef char VexType;  //顶点的数据类型,根据需要定义
typedef int EdgeType;  //边上权值的数据类型,若不带权值的图,则为0或1
typedef struct {
    VexType Vex[MaxVnum];
    EdgeType Edge[MaxVnum][MaxVnum];
    int vexnum, edgenum; //顶点数,边数
}AMGraph;

int locatevex(AMGraph G, VexType x) {
    for (int i = 0; i < G.vexnum; i++)//查找顶点信息的下标
        if (x == G.Vex[i])
            return i;
    return -1;//没找到
}


void CreateAMGraph(AMGraph& G) {
    int i, j;
    VexType u, v;
    cout << "请输入顶点数:" << endl;
    cin >> G.vexnum;
    cout << "请输入边数:" << endl;
    cin >> G.edgenum;
    cout << "请输入顶点信息:" << endl;
    for (int i = 0; i < G.vexnum; i++)//输入顶点信息,存入顶点信息数组
        cin >> G.Vex[i];
    for (int i = 0; i < G.vexnum; i++)//初始化邻接矩阵所有值为0,如果是网,则初始化邻接矩阵为无穷大
        for (int j = 0; j < G.vexnum; j++)
            G.Edge[i][j] = 0;
    cout << "请输入每条边依附的两个顶点:" << endl;
    while (G.edgenum--) {
        cin >> u >> v;
        i = locatevex(G, u);//查找顶点u的存储下标
        j = locatevex(G, v);//查找顶点v的存储下标
        if (i != -1 && j != -1)
            G.Edge[i][j] = G.Edge[j][i] = 1; //邻接矩阵储置1
        else {
            cout << "输入顶点信息错!请重新输入!" << endl;
            G.edgenum++;//本次输入不算
        }
    }
}

void print(AMGraph G) {//输出邻接矩阵
    cout << "图的邻接矩阵为:" << endl;
    for (int i = 0; i < G.vexnum; i++) {
        for (int j = 0; j < G.vexnum; j++)
            cout << G.Edge[i][j] << "\t";
        cout << endl;
    }
}

int main() {
    AMGraph G;
    CreateAMGraph(G);
    print(G);
    return 0;
}
/*
4 5
a b c d
a b
a d
b c
b d
c d
*/

6.1 图的存储2 创建有向图的邻接表

#include//创建有向图的邻接表
using namespace std;
const int MaxVnum = 100;//顶点数最大值
typedef char VexType;//顶点的数据类型为字符型

typedef struct AdjNode { //定义邻接点类型
    int v; //邻接点下标
    struct AdjNode* next; //指向下一个邻接点
}AdjNode;

typedef struct VexNode { //定义顶点类型
    VexType data; // VexType为顶点的数据类型,根据需要定义
    AdjNode* first; //指向第一个邻接点
}VexNode;

typedef struct {//定义邻接表类型
    VexNode Vex[MaxVnum];
    int vexnum, edgenum; //顶点数,边数
}ALGraph;

int locatevex(ALGraph G, VexType x) {
    for (int i = 0; i < G.vexnum; i++)//查找顶点信息的下标
        if (x == G.Vex[i].data)
            return i;
    return -1;//没找到
}

void insertedge(ALGraph& G, int i, int j) {//插入一条边
    AdjNode* s;
    s = new AdjNode;
    s->v = j;
    s->next = G.Vex[i].first;
    G.Vex[i].first = s;
}

void printg(ALGraph G) {//输出邻接表
    cout << "----------邻接表如下:----------" << endl;
    for (int i = 0; i < G.vexnum; i++) {
        AdjNode* t = G.Vex[i].first;
        cout << G.Vex[i].data << ":  ";
        while (t != NULL) {
            cout << "[" << t->v << "]\t";
            t = t->next;
        }
        cout << endl;
    }
}

void CreateALGraph(ALGraph& G) {//创建有向图邻接表
    int i, j;
    VexType u, v;
    cout << "请输入顶点数和边数:" << endl;
    cin >> G.vexnum >> G.edgenum;
    cout << "请输入顶点信息:" << endl;
    for (i = 0; i < G.vexnum; i++)//输入顶点信息,存入顶点信息数组
        cin >> G.Vex[i].data;
    for (i = 0; i < G.vexnum; i++)
        G.Vex[i].first = NULL;
    cout << "请依次输入每条边的两个顶点u,v" << endl;
    while (G.edgenum--) {
        cin >> u >> v;
        i = locatevex(G, u);//查找顶点u的存储下标
        j = locatevex(G, v);//查找顶点v的存储下标
        if (i != -1 && j != -1)
            insertedge(G, i, j);
        else {
            cout << "输入顶点信息错!请重新输入!" << endl;
            G.edgenum++;//本次输入不算
        }
    }
}

int main() {
    ALGraph G;
    CreateALGraph(G);//创建有向图邻接表
    printg(G);//输出邻接表
    return 0;
}
/*
5 7
a b c d e
a b
a c
a e
b c
c d
c e
d e
*/

6.1 图的存储3 创建无向网的链式向前星 

#include//创建无向网的链式前向星 
#include
using namespace std;
const int maxn = 100000 + 5;
int maxx[maxn], head[maxn];
int n, m, x, y, w, cnt;

struct Edge {
	int to, w, next;
}e[maxn];

void add(int u, int v, int w) {//添加一条边u--v 
	e[cnt].to = v;
	e[cnt].w = w;
	e[cnt].next = head[u];
	head[u] = cnt++;
}

void printg() {//输出链式前向星
	cout << "----------链式前向星如下:----------" << endl;
	for (int v = 1; v <= n; v++) {
		cout << v << ":  ";
		for (int i = head[v]; ~i; i = e[i].next) {
			int v1 = e[i].to, w1 = e[i].w;
			cout << "[" << v1 << " " << w1 << "]\t";
		}
		cout << endl;
	}
}

int main() {
	cin >> n >> m;
	memset(head, -1, sizeof(head));
	cnt = 0;
	for (int i = 1; i <= m; i++) {
		cin >> x >> y >> w;
		add(x, y, w);//添加边
		add(y, x, w);//添加反向边 
	}
	printg();
	return 0;
}
/*
4 5
1 2 5
1 4 3
2 3 8
2 4 12
3 4 9
*/

6.2遍历1 基于邻接矩阵的广度优先遍历 

#include
#include//引入队列头文件
using namespace std;
const int MaxVnum = 100;//顶点数最大值
bool visited[MaxVnum];  //访问标志数组,其初值为"false"
typedef char VexType;  //顶点的数据类型,根据需要定义
typedef int EdgeType;  //边上权值的数据类型,若不带权值的图,则为0或1
typedef struct {
    VexType Vex[MaxVnum];
    EdgeType Edge[MaxVnum][MaxVnum];
    int vexnum, edgenum; //顶点数,边数
}AMGraph;

int locatevex(AMGraph G, VexType x) {
    for (int i = 0; i < G.vexnum; i++)//查找顶点信息的下标
        if (x == G.Vex[i])
            return i;
    return -1;//没找到
}

void CreateAMGraph(AMGraph& G) {//创建有向图的邻接矩阵
    int i, j;
    VexType u, v;
    cout << "请输入顶点数:" << endl;
    cin >> G.vexnum;
    cout << "请输入边数:" << endl;
    cin >> G.edgenum;
    cout << "请输入顶点信息:" << endl;
    for (int i = 0; i < G.vexnum; i++)//输入顶点信息,存入顶点信息数组
        cin >> G.Vex[i];
    for (int i = 0; i < G.vexnum; i++)//初始化邻接矩阵所有值为0,如果是网,则初始化邻接矩阵为无穷大
        for (int j = 0; j < G.vexnum; j++)
            G.Edge[i][j] = 0;
    cout << "请输入每条边依附的两个顶点:" << endl;
    while (G.edgenum--) {
        cin >> u >> v;
        i = locatevex(G, u);//查找顶点u的存储下标
        j = locatevex(G, v);//查找顶点v的存储下标
        if (i != -1 && j != -1)
            G.Edge[i][j] = 1; //邻接矩阵储置1,若无向图G.Edge[i][j]=G.Edge[j][i]=1
        else {
            cout << "输入顶点信息错!请重新输入!" << endl;
            G.edgenum++;//本次输入不算
        }
    }
}

void print(AMGraph G) {//输出邻接矩阵
    cout << "图的邻接矩阵为:" << endl;
    for (int i = 0; i < G.vexnum; i++) {
        for (int j = 0; j < G.vexnum; j++)
            cout << G.Edge[i][j] << "\t";
        cout << endl;
    }
}

void BFS_AM(AMGraph G, int v) {//基于邻接矩阵的广度优先遍历
    int u, w;
    queueQ; //创建一个普通队列(先进先出),里面存放int类型
    cout << G.Vex[v] << "\t";
    visited[v] = true;
    Q.push(v); //源点v入队
    while (!Q.empty()) { //如果队列不空
        u = Q.front();//取出队头元素赋值给u
        Q.pop(); //队头元素出队
        for (w = 0; w < G.vexnum; w++) {//依次检查u的所有邻接点
            if (G.Edge[u][w] && !visited[w]) {//u、w邻接而且w未被访问
                cout << G.Vex[w] << "\t";
                visited[w] = true;
                Q.push(w);
            }
        }
    }
}

int main() {
    int v;
    VexType c;
    AMGraph G;
    CreateAMGraph(G);
    print(G);
    cout << "请输入遍历图的起始点:";
    cin >> c;
    v = locatevex(G, c);//查找顶点u的存储下标
    if (v != -1) {
        cout << "广度优先搜索遍历图结果:" << endl;
        BFS_AM(G, v);
    }
    else
        cout << "输入顶点信息错!请重新输入!" << endl;
    return 0;
}
/*测试数据
6 9
1 2 3 4 5 6
1 3
1 2
2 4
3 5
3 2
4 6
4 3
5 6
5 4
1
*/

6.2遍历2 基于邻接表的广度优先遍历

#include
#include//引入队列头文件
using namespace std;
const int MaxVnum = 100;//顶点数最大值
bool visited[MaxVnum];  //访问标志数组,其初值为"false"
typedef char VexType;//顶点的数据类型为字符型

typedef struct AdjNode { //定义邻接点类型
    int v; //邻接点下标
    struct AdjNode* next; //指向下一个邻接点
}AdjNode;

typedef struct VexNode { //定义顶点类型
    VexType data; // VexType为顶点的数据类型,根据需要定义
    AdjNode* first; //指向第一个邻接点
}VexNode;

typedef struct {//定义邻接表类型
    VexNode  Vex[MaxVnum];
    int vexnum, edgenum; //顶点数,边数
}ALGraph;

int locatevex(ALGraph G, VexType x) {
    for (int i = 0; i < G.vexnum; i++)//查找顶点信息的下标
        if (x == G.Vex[i].data)
            return i;
    return -1;//没找到
}

void insertedge(ALGraph& G, int i, int j) {//插入一条边
    AdjNode* s;
    s = new AdjNode;
    s->v = j;
    s->next = G.Vex[i].first;
    G.Vex[i].first = s;
}

void printg(ALGraph G) {//输出邻接表
    cout << "----------邻接表如下:----------" << endl;
    for (int i = 0; i < G.vexnum; i++) {
        AdjNode* t = G.Vex[i].first;
        cout << G.Vex[i].data << ":  ";
        while (t != NULL) {
            cout << "[" << t->v << "]  ";
            t = t->next;
        }
        cout << endl;
    }
}

void CreateALGraph(ALGraph& G) {//创建有向图邻接表
    int i, j;
    VexType u, v;
    cout << "请输入顶点数和边数:" << endl;
    cin >> G.vexnum >> G.edgenum;
    cout << "请输入顶点信息:" << endl;
    for (i = 0; i < G.vexnum; i++)//输入顶点信息,存入顶点信息数组
        cin >> G.Vex[i].data;
    for (i = 0; i < G.vexnum; i++)
        G.Vex[i].first = NULL;
    cout << "请依次输入每条边的两个顶点u,v" << endl;
    while (G.edgenum--) {
        cin >> u >> v;
        i = locatevex(G, u);//查找顶点u的存储下标
        j = locatevex(G, v);//查找顶点v的存储下标
        if (i != -1 && j != -1)
            insertedge(G, i, j);
        else {
            cout << "输入顶点信息错!请重新输入!" << endl;
            G.edgenum++;//本次输入不算
        }
    }
}

void BFS_AL(ALGraph G, int v) {//基于邻接表的广度优先遍历
    int u, w;
    AdjNode* p;
    queueQ; //创建一个普通队列(先进先出),里面存放int类型
    cout << G.Vex[v].data << "\t";
    visited[v] = true;
    Q.push(v); //源点v入队
    while (!Q.empty()) { //如果队列不空
        u = Q.front();//取出队头元素赋值给u
        Q.pop(); //队头元素出队
        p = G.Vex[u].first;
        while (p) {//依次检查u的所有邻接点
            w = p->v;//w为u的邻接点
            if (!visited[w]) {//w未被访问
                cout << G.Vex[w].data << "\t";
                visited[w] = true;
                Q.push(w);
            }
            p = p->next;
        }
    }
}

void BFS_AL(ALGraph G) {//非连通图,基于邻接表的广度优先遍历
    for (int i = 0; i < G.vexnum; i++)//非连通图需要查漏点,检查未被访问的顶点
        if (!visited[i])//i未被访问,以i为起点再次广度优先遍历
            BFS_AL(G, i);
}

int main() {
    ALGraph G;
    int v;
    VexType c;
    CreateALGraph(G);//创建有向图邻接表
    printg(G);//输出邻接表
    cout << "请输入遍历图的起始点:";
    cin >> c;
    v = locatevex(G, c);//查找顶点u的存储下标
    if (v != -1) {
        cout << "广度优先搜索遍历图结果:" << endl;
        BFS_AL(G, v);
    }
    else
        cout << "输入顶点信息错!请重新输入!" << endl;
    return 0;
}
/*测试数据
6 9
1 2 3 4 5 6
1 3
1 2
2 4
3 5
3 2
4 6
4 3
5 6
5 4
1
*/

6.2遍历3 基于邻接矩阵的深度优先遍历

#include
using namespace std;
const int MaxVnum = 100;     //顶点数最大值
bool visited[MaxVnum];  //访问标志数组,其初值为"false"
typedef char VexType;  //顶点的数据类型,根据需要定义
typedef int EdgeType;  //边上权值的数据类型,若不带权值的图,则为0或1
typedef struct {
    VexType Vex[MaxVnum];
    EdgeType Edge[MaxVnum][MaxVnum];
    int vexnum, edgenum; //顶点数,边数
}AMGraph;

int locatevex(AMGraph G, VexType x) {
    for (int i = 0; i < G.vexnum; i++)//查找顶点信息的下标
        if (x == G.Vex[i])
            return i;
    return -1;//没找到
}

void CreateAMGraph(AMGraph& G) {//创建无向图的邻接矩阵
    int i, j;
    VexType u, v;
    cout << "请输入顶点数:" << endl;
    cin >> G.vexnum;
    cout << "请输入边数:" << endl;
    cin >> G.edgenum;
    cout << "请输入顶点信息:" << endl;
    for (int i = 0; i < G.vexnum; i++)//输入顶点信息,存入顶点信息数组
        cin >> G.Vex[i];
    for (int i = 0; i < G.vexnum; i++)//初始化邻接矩阵所有值为0,如果是网,则初始化邻接矩阵为无穷大
        for (int j = 0; j < G.vexnum; j++)
            G.Edge[i][j] = 0;
    cout << "请输入每条边依附的两个顶点:" << endl;
    while (G.edgenum--) {
        cin >> u >> v;
        i = locatevex(G, u);//查找顶点u的存储下标
        j = locatevex(G, v);//查找顶点v的存储下标
        if (i != -1 && j != -1)
            G.Edge[i][j] = G.Edge[j][i] = 1; //若有向图G.Edge[i][j]=1
        else {
            cout << "输入顶点信息错!请重新输入!" << endl;
            G.edgenum++;//本次输入不算
        }
    }
}

void print(AMGraph G) {//输出邻接矩阵
    cout << "图的邻接矩阵为:" << endl;
    for (int i = 0; i < G.vexnum; i++) {
        for (int j = 0; j < G.vexnum; j++)
            cout << G.Edge[i][j] << "\t";
        cout << endl;
    }
}

void DFS_AM(AMGraph G, int v) {//基于邻接矩阵的深度优先遍历
    int w;
    cout << G.Vex[v] << "\t";
    visited[v] = true;
    for (w = 0; w < G.vexnum; w++)//依次检查v的所有邻接点
        if (G.Edge[v][w] && !visited[w])//v、w邻接而且w未被访问
            DFS_AM(G, w);//从w顶点开始递归深度优先遍历
}

int main() {
    int v;
    VexType c;
    AMGraph G;
    CreateAMGraph(G);//创建无向图的邻接矩阵 
    print(G);
    cout << "请输入遍历连通图的起始点:";
    cin >> c;
    v = locatevex(G, c);//查找顶点u的存储下标
    if (v != -1) {
        cout << "深度优先搜索遍历连通图结果:" << endl;
        DFS_AM(G, v);
    }
    else
        cout << "输入顶点信息错!请重新输入!" << endl;
    return 0;
}
/*测试数据
8 9
1 2 3 4 5 6 7 8
1 3
1 2
2 6
2 5
2 4
3 8
3 7
4 5
7 8
1
*/

6.2遍历4 基于邻接表的深度优先遍历

#include
using namespace std;
const int MaxVnum = 100;  //顶点数最大值
bool visited[MaxVnum];  //访问标志数组,其初值为"false"
typedef char VexType;   //顶点的数据类型为字符型
typedef struct AdjNode { //定义邻接点类型
    int v; //邻接点下标
    struct AdjNode* next; //指向下一个邻接点
}AdjNode;

typedef struct VexNode { //定义顶点类型
    VexType data; // VexType为顶点的数据类型,根据需要定义
    AdjNode* first; //指向第一个邻接点
}VexNode;

typedef struct {//定义邻接表类型
    VexNode  Vex[MaxVnum];
    int vexnum, edgenum; //顶点数,边数
}ALGraph;

int locatevex(ALGraph G, VexType x) {
    for (int i = 0; i < G.vexnum; i++)//查找顶点信息的下标
        if (x == G.Vex[i].data)
            return i;
    return -1;//没找到
}

void insertedge(ALGraph& G, int i, int j) {//插入一条边
    AdjNode* s;
    s = new AdjNode;
    s->v = j;
    s->next = G.Vex[i].first;
    G.Vex[i].first = s;
}

void printg(ALGraph G) {//输出邻接表
    cout << "----------邻接表如下:----------" << endl;
    for (int i = 0; i < G.vexnum; i++) {
        AdjNode* t = G.Vex[i].first;
        cout << G.Vex[i].data << ":  ";
        while (t != NULL) {
            cout << "[" << t->v << "]  ";
            t = t->next;
        }
        cout << endl;
    }
}

void CreateALGraph(ALGraph& G) {//创建无向图邻接表
    int i, j;
    VexType u, v;
    cout << "请输入顶点数和边数:" << endl;
    cin >> G.vexnum >> G.edgenum;
    cout << "请输入顶点信息:" << endl;
    for (i = 0; i < G.vexnum; i++)//输入顶点信息,存入顶点信息数组
        cin >> G.Vex[i].data;
    for (i = 0; i < G.vexnum; i++)
        G.Vex[i].first = NULL;
    cout << "请依次输入每条边的两个顶点u,v" << endl;
    while (G.edgenum--) {
        cin >> u >> v;
        i = locatevex(G, u);//查找顶点u的存储下标
        j = locatevex(G, v);//查找顶点v的存储下标
        if (i != -1 && j != -1) {
            insertedge(G, i, j);
            insertedge(G, j, i);//无向图多插入一条边
        }
        else {
            cout << "输入顶点信息错!请重新输入!" << endl;
            G.edgenum++;//本次输入不算
        }
    }
}

void DFS_AL(ALGraph G, int v) {//基于邻接表的深度优先遍历
    int w;
    AdjNode* p;
    cout << G.Vex[v].data << "\t";
    visited[v] = true;
    p = G.Vex[v].first;
    while (p) {//依次检查v的所有邻接点
        w = p->v;//w为v的邻接点
        if (!visited[w])//w未被访问
            DFS_AL(G, w);//从w出发,递归深度优先遍历
        p = p->next;
    }
}

void DFS_AL(ALGraph G) {//非连通图,基于邻接表的深度优先遍历
    for (int i = 0; i < G.vexnum; i++)//非连通图需要查漏点,检查未被访问的顶点
        if (!visited[i])//i未被访问,以i为起点再次深度优先遍历
            DFS_AL(G, i);
}

int main() {
    ALGraph G;
    int v;
    VexType c;
    CreateALGraph(G);//创建无向图的邻接表
    printg(G);//输出邻接表
    cout << "请输入遍历连通图的起始点:";
    cin >> c;
    v = locatevex(G, c);//查找顶点u的存储下标
    if (v != -1) {
        cout << "深度优先搜索遍历连通图结果:" << endl;
        DFS_AL(G, v);
    }
    else
        cout << "输入顶点信息错!请重新输入!" << endl;
    return 0;
}
/*测试数据
8 9
1 2 3 4 5 6 7 8
1 3
1 2
2 6
2 5
2 4
3 8
3 7
4 5
7 8
1
*/

7.1 最短路径 

7.1 最短路径1 dijkstra 

#include
#include
#include
using namespace std;
const int MaxVnum = 100; //城市的个数可修改
const int INF = 0x3f3f3f3f; //无穷大
int dist[MaxVnum], p[MaxVnum];//最短距离和前驱数组
bool flag[MaxVnum]; //如果s[i]等于true,说明顶点i已经加入到集合S;否则顶点i属于集合V-S
typedef string VexType;  //顶点的数据类型,根据需要定义
typedef int EdgeType;  //边上权值的数据类型,若不带权值的图,则为0或1
typedef struct {
	VexType Vex[MaxVnum];
	EdgeType Edge[MaxVnum][MaxVnum];
	int vexnum, edgenum; //顶点数,边数
}AMGraph;

int locatevex(AMGraph G, VexType x) {
	for (int i = 0; i < G.vexnum; i++)//查找顶点信息的下标
		if (x == G.Vex[i])
			return i;
	return -1;//没找到
}

void CreateAMGraph(AMGraph& G) {
	int i, j, w;
	VexType u, v;
	cout << "请输入顶点数:" << endl;
	cin >> G.vexnum;
	cout << "请输入边数:" << endl;
	cin >> G.edgenum;
	cout << "请输入顶点信息:" << endl;
	for (int i = 0; i < G.vexnum; i++)//输入顶点信息,存入顶点信息数组
		cin >> G.Vex[i];
	for (int i = 0; i < G.vexnum; i++)//初始化邻接矩阵为无穷大
		for (int j = 0; j < G.vexnum; j++)
			G.Edge[i][j] = INF;
	cout << "请输入每条边依附的两个顶点及权值:" << endl;
	while (G.edgenum--) {
		cin >> u >> v >> w;
		i = locatevex(G, u);//查找顶点u的存储下标
		j = locatevex(G, v);//查找顶点v的存储下标
		if (i != -1 && j != -1)
			G.Edge[i][j] = w; //有向图邻接矩阵
		else {
			cout << "输入顶点信息错!请重新输入!" << endl;
			G.edgenum++;//本次输入不算
		}
	}
}

void Dijkstra(AMGraph G, int u) {
	for (int i = 0; i < G.vexnum; i++) {
		dist[i] = G.Edge[u][i]; //初始化源点u到其他各个顶点的最短路径长度
		flag[i] = false;
		if (dist[i] == INF)
			p[i] = -1; //源点u到该顶点的路径长度为无穷大,说明顶点i与源点u不相邻
		else
			p[i] = u; //说明顶点i与源点u相邻,设置顶点i的前驱p[i]=u
	}
	dist[u] = 0;
	flag[u] = true;   //初始时,集合S中只有一个元素:源点u
	for (int i = 0; i < G.vexnum; i++) {
		int temp = INF, t = u;
		for (int j = 0; j < G.vexnum; j++) //在集合V-S中寻找距离源点u最近的顶点t
			if (!flag[j] && dist[j] < temp) {
				t = j;
				temp = dist[j];
			}
		if (t == u) return; //找不到t,跳出循环
		flag[t] = true;  //否则,将t加入集合
		for (int j = 0; j < G.vexnum; j++)//更新V-S中与t相邻接的顶点到源点u的距离
			if (!flag[j] && G.Edge[t][j] < INF)
				if (dist[j] > (dist[t] + G.Edge[t][j])) {
					dist[j] = dist[t] + G.Edge[t][j];
					p[j] = t;
				}
	}
}

void findpath(AMGraph G, VexType u) {
	int x;
	stackS;
	cout << "源点为:" << u << endl;
	for (int i = 0; i < G.vexnum; i++) {
		x = p[i];
		if (x == -1 && u != G.Vex[i]) {
			cout << "源点到其它各顶点最短路径为:" << u << "--" << G.Vex[i] << "    sorry,无路可达" << endl;
			continue;
		}
		while (x != -1) {
			S.push(x);
			x = p[x];
		}
		cout << "源点到其它各顶点最短路径为:";
		while (!S.empty()) {
			cout << G.Vex[S.top()] << "--";
			S.pop();
		}
		cout << G.Vex[i] << "    最短距离为:" << dist[i] << endl;
	}
}

int main() {
	AMGraph G;
	int st;
	VexType u;
	CreateAMGraph(G);
	cout << "请输入源点的信息:" << endl;
	cin >> u;
	st = locatevex(G, u);//查找源点u的存储下标
	Dijkstra(G, st);
	cout << "小明所在的位置:" << u << endl;
	for (int i = 0; i < G.vexnum; i++) {
		cout << "小明:" << u << " - " << "要去的位置:" << G.Vex[i];
		if (dist[i] == INF)
			cout << " sorry,无路可达" << endl;
		else
			cout << " 最短距离为:" << dist[i] << endl;
	}
	findpath(G, u);
	return 0;
}
/*
5 8
1 2 3 4 5
1 2 2
1 3 5
2 3 2
2 4 6
3 4 7
3 5 1
4 3 2
4 5 4
1
*/

7.1 最短路径2 Floyd

#include
#include
using namespace std;
const int MaxVnum = 100; //顶点数最大值
const int INF = 0x3f3f3f3f; // 无穷大
typedef string VexType;  //顶点的数据类型,根据需要定义
typedef int EdgeType;  //边上权值的数据类型,若不带权值的图,则为0或1
typedef struct {
    VexType Vex[MaxVnum];
    EdgeType Edge[MaxVnum][MaxVnum];
    int vexnum, edgenum; //顶点数,边数
}AMGraph;
int dist[MaxVnum][MaxVnum], p[MaxVnum][MaxVnum];

int locatevex(AMGraph G, VexType x) {
    for (int i = 0; i < G.vexnum; i++)//查找顶点信息的下标
        if (x == G.Vex[i])
            return i;
    return -1;//没找到
}

void CreateAMGraph(AMGraph& G) {//创建无向图的邻接矩阵
    int i, j, w;
    VexType u, v;
    cout << "请输入顶点数:" << endl;
    cin >> G.vexnum;
    cout << "请输入边数:" << endl;
    cin >> G.edgenum;
    cout << "请输入顶点信息:" << endl;
    for (int i = 0; i < G.vexnum; i++)//输入顶点信息,存入顶点信息数组
        cin >> G.Vex[i];
    for (int i = 0; i < G.vexnum; i++)//初始化邻接矩阵所有值为0,若是网,则初始化为无穷大
        for (int j = 0; j < G.vexnum; j++)
            if (i != j)
                G.Edge[i][j] = INF;
            else
                G.Edge[i][j] = 0; //注意i==j时,设置为0
    cout << "请输入每条边依附的两个顶点及权值:" << endl;
    while (G.edgenum--) {
        cin >> u >> v >> w;
        i = locatevex(G, u);//查找顶点u的存储下标
        j = locatevex(G, v);//查找顶点v的存储下标
        if (i != -1 && j != -1)
            G.Edge[i][j] = w; //有向图邻接矩阵存储权值
    }
}

void Floyd(AMGraph G) { //用Floyd算法求有向网G中各对顶点i和j之间的最短路径
    int i, j, k;
    for (i = 0; i < G.vexnum; i++)          		//各对结点之间初始已知路径及距离
        for (j = 0; j < G.vexnum; j++) {
            dist[i][j] = G.Edge[i][j];
            if (dist[i][j] < INF && i != j)
                p[i][j] = i;  	//如果i和j之间有弧,则将j的前驱置为i
            else p[i][j] = -1;  //如果i和j之间无弧,则将j的前驱置为-1
        }
    for (k = 0; k < G.vexnum; k++)
        for (i = 0; i < G.vexnum; i++)
            for (j = 0; j < G.vexnum; j++)
                if (dist[i][k] + dist[k][j] < dist[i][j]) {//从i经k到j的一条路径更短
                    dist[i][j] = dist[i][k] + dist[k][j]; //更新dist[i][j]
                    p[i][j] = p[k][j];   //更改j的前驱
                }
}

void print(AMGraph G) {
    int i, j;
    for (i = 0; i < G.vexnum; i++) {//输出最短距离数组
        for (j = 0; j < G.vexnum; j++)
            cout << dist[i][j] << "\t";
        cout << endl;
    }
    cout << endl;
    for (i = 0; i < G.vexnum; i++) {//输出前驱数组
        for (j = 0; j < G.vexnum; j++)
            cout << p[i][j] << "\t";
        cout << endl;
    }
}

void DisplayPath(AMGraph G, int s, int t) {//显示最短路径
    if (p[s][t] != -1) {
        DisplayPath(G, s, p[s][t]);
        cout << G.Vex[p[s][t]] << "-->";
    }
}

int main() {
    VexType start, destination;
    int u, v;
    AMGraph G;
    CreateAMGraph(G);
    Floyd(G);
    print(G);
    cout << "请依次输入路径的起点与终点的名称:";
    cin >> start >> destination;
    u = locatevex(G, start);
    v = locatevex(G, destination);
    DisplayPath(G, u, v);
    cout << G.Vex[v] << endl;
    cout << "最短路径的长度为:" << dist[u][v] << endl;
    cout << endl;
    return 0;
}
/*
4 8
0 1 2 3
0 1 1
0 3 4
1 2 9
1 3 2
2 0 3
2 1 5
2 3 8
3 2 6
0 2
*/

7.1 最短路径3 bellman ford

#include
#include
using namespace std;
struct node {
	int a, b, w;
}e[210];
int dis[110];
int n, m, cnt = 0;

void add(int a, int b, int w) {
	e[cnt].a = a;
	e[cnt].b = b;
	e[cnt++].w = w;
}

bool bellman_ford(int u) {//求源点u到其它顶点的最短路径长度,判负环 
	memset(dis, 0x3f, sizeof(dis));
	dis[u] = 0;
	for (int i = 1; i < n; i++) {//执行n-1次
		bool flag = false;
		for (int j = 0; j < m; j++)//边数m或cnt
			if (dis[e[j].b] > dis[e[j].a] + e[j].w) {
				dis[e[j].b] = dis[e[j].a] + e[j].w;
				flag = true;
			}
		if (!flag)
			return false;
	}
	for (int j = 0; j < m; j++)//再执行1次,还能松弛说明有环
		if (dis[e[j].b] > dis[e[j].a] + e[j].w)
			return true;
	return false;
}

void print() {//输出源点到其它节点的最短距离 
	cout << "最短距离:" << endl;
	for (int i = 1; i <= n; i++)
		cout << dis[i] << " ";
	cout << endl;
}

int main() {
	int a, b, w;
	cin >> n >> m;
	for (int i = 0; i < m; i++) {
		cin >> a >> b >> w;
		add(a, b, w);
	}
	if (bellman_ford(1))//判断负环
		cout << "有负环!" << endl;
	else
		print();
	return 0;
}
/*测试数据1
5 8
1 2 2
1 3 5
2 3 2
2 4 6
3 4 7
3 5 1
4 3 2
4 5 4
*/
/*测试数据2,有负环
4 4
1 2 3
2 3 -4
3 4 2
4 2 1
*/

7.1 最短路径4 spfa

#include
#include
#include
using namespace std;
const int maxn = 505, maxe = 100001;
int n, m, cnt;
int head[maxn], dis[maxn], sum[maxn];
bool vis[maxn];//标记是否在队列中 
struct node {
	int to, next, w;
}e[maxe];

void add(int u, int v, int w) {
	e[cnt].to = v;
	e[cnt].next = head[u];
	e[cnt].w = w;
	head[u] = cnt++;
}

bool spfa(int u) {
	queueq;
	memset(vis, 0, sizeof(vis));//标记是否在队列中
	memset(sum, 0, sizeof(sum));//统计入队的次数
	memset(dis, 0x3f, sizeof(dis));
	vis[u] = 1;
	dis[u] = 0;
	sum[u]++;
	q.push(u);
	while (!q.empty()) {
		int x = q.front();
		q.pop();
		vis[x] = 0;
		for (int i = head[x]; ~i; i = e[i].next) {
			int v = e[i].to;
			if (dis[v] > dis[x] + e[i].w) {
				dis[v] = dis[x] + e[i].w;
				if (!vis[v]) {
					if (++sum[v] >= n)
						return true;
					vis[v] = 1;
					q.push(v);
				}
			}
		}
	}
	return false;
}

void print() {//输出源点到其它节点的最短距离 
	cout << "最短距离:" << endl;
	for (int i = 1; i <= n; i++)
		cout << dis[i] << " ";
	cout << endl;
}

int main() {
	cnt = 0;
	cin >> n >> m;
	memset(head, -1, sizeof(head));
	int u, v, w;
	for (int i = 1; i <= m; i++) {
		cin >> u >> v >> w;
		add(u, v, w);
	}
	if (spfa(1))
		cout << "有负环!" << endl;
	else
		print();
	return 0;
}
/*测试数据1
5 8
1 2 2
1 3 5
2 3 2
2 4 6
3 4 7
3 5 1
4 3 2
4 5 4
*/
/*测试数据2,有负环
4 4
1 2 3
2 3 -4
3 4 2
4 2 1
*/

7.2  最小生成树

Prim

#include
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 100;
bool s[N];//如果s[i]=true,说明顶点i已加入U
int c[N][N], closest[N], lowcost[N];

void Prim(int n) {
    s[1] = true; //初始时,集合中U只有一个元素,即顶点1
    for (int i = 1; i <= n; i++) {
        if (i != 1) {
            lowcost[i] = c[1][i];
            closest[i] = 1;
            s[i] = false;
        }
        else
            lowcost[i] = 0;
    }
    for (int i = 1; i < n; i++) {
        int temp = INF;
        int t = 1;
        for (int j = 1; j <= n; j++) {//在集合中V-u中寻找距离集合U最近的顶点t
            if (!s[j] && lowcost[j] < temp) {
                t = j;
                temp = lowcost[j];
            }
        }
        if (t == 1)
            break;//找不到t,跳出循环
        s[t] = true;//否则,t加入集合U
        for (int j = 1; j <= n; j++) { //更新lowcost和closest
            if (!s[j] && c[t][j] < lowcost[j]) {
                lowcost[j] = c[t][j];
                closest[j] = t;
            }
        }
    }
}

int main() {
    int n, m, u, v, w;
    cin >> n >> m;
    int sumcost = 0;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            c[i][j] = INF;
    for (int i = 1; i <= m; i++) {
        cin >> u >> v >> w;
        c[u][v] = c[v][u] = w;
    }
    Prim(n);
    cout << "数组lowcost:" << endl;
    for (int i = 1; i <= n; i++)
        cout << lowcost[i] << " ";
    cout << endl;
    for (int i = 1; i <= n; i++)
        sumcost += lowcost[i];
    cout << "最小的花费:" << sumcost << endl;
    return 0;
}
/*测试数据
7 12
1 2 23
1 6 28
1 7 36
2 3 20
2 7 1
3 4 15
3 7 4
4 5 3
4 7 9
5 6 17
5 7 16
6 7 25

输出结果:
数组lowcost:
0 23 4 9 3 17 1
最小的花费:57
*/

Kruskal

#include
#include
using namespace std;
const int N=100;
int fa[N];
int n,m;
struct Edge{
    int u,v,w;
}e[N*N];

bool cmp(Edge x, Edge y){
    return x.w>n>>m;
    Init(n);
    for(int i=1;i<=m;i++)
        cin>>e[i].u>>e[i].v>>e[i].w;
    cout<<"最小的花费是:"<

 Kruskal_2

#include
#include
using namespace std;
const int N=100;
int fa[N];
int n,m;

struct Edge{
    int u,v,w;
}e[N*N];

bool cmp(Edge x,Edge y){
    return x.w>n>>m;
    Init(n);
    for(int i=1;i<=m;i++)
        cin>>e[i].u>>e[i].v>>e[i].w;
    cout<<"最小的花费:"<

7.3拓扑排序

Topo sort

#include
#include
#include
using namespace std;
const int maxn=105;
int map[maxn][maxn],indegree[maxn],topo[maxn];
int n,m;
stacks;

bool TopoSort(){ //拓扑排序
	int cnt=0;
    for(int i=0;i>n>>m;
    memset(map,0,sizeof(map));
    memset(indegree,0,sizeof(indegree));
	for(int i=0;i>u>>v;
    	map[u][v]=1;
    	indegree[v]++;
	}
	TopoSort();
	for(int i=0;i

 7.4 关键路径

CriticalPath

#include
#include
#include
using namespace std;
const int maxn=10010,maxe=50010;
int n,m,cnt;
int head[maxn]; //链式前向星头 
int in[maxn],topo[maxn]; //入度,拓扑序列 
int ve[maxn]; //事件vi的最早发生时间
int vl[maxn]; //事件vi的最迟发生时间
stacks;
struct node{
	int to,next,w;
}e[maxe];

void add(int u,int v,int w){
	e[cnt].to=v;
	e[cnt].next=head[u];
	head[u]=cnt;
	e[cnt++].w=w;
}

bool TopoSort(){//拓扑排序
	int cnt=0;
    for(int i=0;i=0;j--){//按逆拓扑序求每个事件的最迟发生时间
		int u=topo[j];  //取得拓扑序列中的顶点
		for(int i=head[u];~i;i=e[i].next){
    		int v=e[i].to,w=e[i].w;
            if(vl[u]>vl[v]-w)
        		vl[u]=vl[v]-w;
		}
    }
    cout<<"事件的最早发生时间和最迟发生时间:"<的最早开始时间e
			int l=vl[v]-w; //计算活动的最迟开始时间l
			if(e==l)   //若为关键活动,则输出
				cout<<"<"<"<>n>>m;
	memset(head,-1,sizeof(head));
    memset(in,0,sizeof(in));
    for(int i=0;i>u>>v>>w;
        add(u,v,w);
        in[v]++;
    }
    CriticalPath();
    return 0;
}
/*测试数据 
6 8
0 1 2
0 2 15
1 3 10
1 4 19
2 1 4
2 4 11
3 5 6
4 5 5
*/

8.1 哈希表 

Hash

#include
#include
#include
using namespace std;
#define m 15//哈希表的表长
#define NULLKEY 0//单元为空的标记
int HT[m],HC[m];

int H(int key){//哈希函数
	return key%13;
}

int Linedetect(int HT[],int H0,int key,int &cnt){
    int Hi;
    for(int i=1;i>x;
		if(!InsertHash(HT,x)){
		    cout<<"创建哈希表失败!"<>x;
	int result=SearchHash(HT,x);
	if(result!=-1)
		cout<<"在第"<

8.2  字符串模式匹配

BF

#include
#include
using namespace std;

int BF(string s,string t,int pos){
	int i=pos,j=0,sum=0;
	int slen=s.length();
	int tlen=t.length();
	while(i=tlen) // 匹配成功
		return i-tlen+1;
	else
		return 0;
}

int main(){
	string s,t;
	cin>>s>>t;
	cout<

 KMP

#include
#include
using namespace std;
int slen,tlen,next[1000+5];

void get_next(string t){//求模式串T的next函数
	int j=0,k=-1;
	next[0]=-1;
	while(j=tlen) // 匹配成功
		return i-tlen+1;
	else
		return -1;
}

int main(){
	string s,t;
	cin>>s>>t;
	cout<

8.3  二叉查找树

bst

#include
using namespace std;
#define ENDFLAG -1
typedef int ElemType;

typedef struct BSTNode{
	ElemType data;	//结点数据域
	BSTNode *lchild,*rchild;	//左右孩子指针
}BSTNode,*BSTree;

BSTree SearchBST(BSTree T,ElemType key)//二叉排序树的递归查找
{
    //若查找成功,则返回指向该数据元素结点的指针,否则返回空指针
    if((!T)|| key==T->data)
        return T;
    else if (keydata)
            return SearchBST(T->lchild,key);//在左子树中继续查找
        else
            return SearchBST(T->rchild,key); //在右子树中继续查找
}

void InsertBST(BSTree &T,ElemType e)//二叉排序树的插入
{
    //当二叉排序树T中不存在关键字等于e的数据元素时,则插入该元素
    if(!T)
    {
        BSTree S=new BSTNode; //生成新结点
        S->data=e;             //新结点S的数据域置为e
        S->lchild=S->rchild=NULL;//新结点S作为叶子结点
        T=S;            		//把新结点S链接到已找到的插入位置
    }
    else if(edata)
            InsertBST(T->lchild,e );//插入左子树
        else if(e>T->data)
            InsertBST(T->rchild,e);//插入右子树
}

void CreateBST(BSTree &T )//二叉排序树的创建
{
    //依次读入一个关键字为key的结点,将此结点插入二叉排序树T中
    T=NULL;
    ElemType e;
    cin>>e;
    while(e!=ENDFLAG)//ENDFLAG为自定义常量,作为输入结束标志
    {
        InsertBST(T,e);  //插入二叉排序树T中
        cin>>e;
    }
}

void DeleteBST(BSTree &T,char key)
{
  //从二叉排序树T中删除关键字等于key的结点
    BSTree p=T;BSTree f=NULL;
    BSTree q;
    BSTree s;
    if(!T) return; //树为空则返回
    while(p)//查找
    {
        if(p->data==key) break;  //找到关键字等于key的结点p,结束循环
        f=p;                //f为p的双亲
        if (p->data>key)
            p=p->lchild; //在p的左子树中继续查找
        else
            p=p->rchild; //在p的右子树中继续查找
    }
    if(!p) return; //找不到被删结点则返回
    //三种情况:p左右子树均不空、无右子树、无左子树
    if((p->lchild)&&(p->rchild))//被删结点p左右子树均不空
    {
        q=p;
        s=p->lchild;
        while(s->rchild)//在p的左子树中继续查找其前驱结点,即最右下结点
        {
            q=s;
            s=s->rchild;
        }
        p->data=s->data;  //s的值赋值给被删结点p,然后删除s结点
        if(q!=p)
            q->rchild=s->lchild; //重接q的右子树
        else
            q->lchild=s->lchild; //重接q的左子树
        delete s;
    }
    else
    {
        if(!p->rchild)//被删结点p无右子树,只需重接其左子树
        {
            q=p;
            p=p->lchild;
        }
        else if(!p->lchild)//被删结点p无左子树,只需重接其右子树
        {
             q=p;
             p=p->rchild;
        }
        /*――――――――――将p所指的子树挂接到其双亲结点f相应的位置――――――――*/
        if(!f)
            T=p;  //被删结点为根结点
        else if(q==f->lchild)
                f->lchild=p; //挂接到f的左子树位置
            else
                f->rchild=p;//挂接到f的右子树位置
        delete q;
	}
}

void InOrderTraverse(BSTree &T)//中序遍历
{
    if(T)
	{
        InOrderTraverse(T->lchild);
        cout<data<<"\t";
        InOrderTraverse(T->rchild);
	}
}

int main()
{
	BSTree T;
	cout<<"请输入一些整型数,-1结束"<>key;
	BSTree result=SearchBST(T,key);
	if(result)
        cout<<"找到"<>key;
	DeleteBST(T,key);
	cout<<"当前有序二叉树中序遍历结果为"<

8.4  平衡二叉树

#include
#include
#include
using namespace std;

typedef struct AVLNode{
   int data;
   int height;
   struct AVLNode *lchild;
   struct AVLNode *rchild;
}*AVLTree;

AVLTree Empty(AVLTree &T)//删除树
{
    if(T==NULL) return NULL;
    Empty(T->lchild);
    Empty(T->rchild);
    delete T;
    return NULL;
}

inline int Height(AVLTree T)//计算高度
{
    if(T==NULL) return 0;
    return T->height;
}

void updateHeight(AVLTree &T)
{
     T->height=max(Height(T->lchild),Height(T->rchild))+1;
}

AVLTree LL_Rotation(AVLTree &T)//LL旋转
{
    AVLTree temp=T->lchild;
    T->lchild=temp->rchild;
    temp->rchild=T;
    updateHeight(T);//更新高度
    updateHeight(temp);
    return temp;
}

AVLTree RR_Rotation(AVLTree &T)//RR旋转
{
    AVLTree temp=T->rchild;
    T->rchild=temp->lchild;
    temp->lchild=T;
    updateHeight(T);//更新高度
    updateHeight(temp);
    return temp;
}

AVLTree LR_Rotation(AVLTree &T)//LR旋转
{
     T->lchild=RR_Rotation(T->lchild);
     return LL_Rotation(T);
}

AVLTree RL_Rotation(AVLTree &T)//RL旋转
{
    T->rchild=LL_Rotation(T->rchild);
    return RR_Rotation(T);
}

AVLTree Insert(AVLTree &T,int x)
{
    if(T==NULL) //如果为空,创建新结点
    {
        T=new AVLNode;
        T->lchild=T->rchild=NULL;
        T->data=x;
        T->height=1;
        return T;
     }
    if(T->data==x) return T;//查找成功,什么也不做,查找失败时才插入
    if(xdata)//插入到左子树
    {
        T->lchild=Insert(T->lchild,x);//注意插入后饭后结果挂接到T->lchild
        if(Height(T->lchild)-Height(T->rchild)==2)//插入后看是否平衡,如果不平衡显然是插入的那一边高度大
        {                                         //沿着高度大的那条路径判断
            if(xlchild->data)//判断是LL还是LR,即插入的是lchild节点的lchild 还是rchild
                T=LL_Rotation(T);
            else
                T=LR_Rotation(T);
        }
    }
    else//插入到右子树
    {
        T->rchild=Insert(T->rchild,x);
        if(Height(T->rchild)-Height(T->lchild)==2)
        {
            if(x>T->rchild->data)
                T=RR_Rotation(T);
            else
                T=RL_Rotation(T);
        }
    }
    updateHeight(T);
    return T;
}

AVLTree adjust(AVLTree &T)//删除结点后,需要判断是否还是平衡,如果不平衡,就要调整
{
    if(T==NULL) return NULL;
    if(Height(T->lchild)-Height(T->rchild)==2)//沿着高度大的那条路径判断
    {
        if(Height(T->lchild->lchild)>=Height(T->lchild->rchild))
            T=LL_Rotation(T);
        else
            T=LR_Rotation(T);
    }
    if(Height(T->rchild)-Height(T->lchild)==2)//沿着高度大的那条路径判断
    {
        if(Height(T->rchild->rchild)>=Height(T->rchild->lchild))
            T=RR_Rotation(T);
        else
            T=RL_Rotation(T);
    }
    updateHeight(T);
    return T;
}

AVLTree Delete(AVLTree &T,int x)
{
    if(T==NULL) return NULL;
    if(T->data==x)//如果找到删除节点
    {
        if(T->rchild==NULL)//如果该节点的右孩子为NULL,那么直接删除
        {
            AVLTree temp=T;
            T=T->lchild;
            delete temp;
        }
        else//否则,将其右子树的最左孩子作为这个节点,并且递归删除这个节点的值
        {
           AVLTree temp;
           temp=T->rchild;
           while(temp->lchild)
              temp=temp->lchild;
           T->data=temp->data;
           T->rchild=Delete(T->rchild,T->data);
           updateHeight(T);
        }
        return T;
    }

    if(T->data>x)//调节删除节点后可能涉及的节点
        T->lchild=Delete(T->lchild,x);
    if(T->datarchild=Delete(T->rchild,x);
    updateHeight(T);
	T=adjust(T);
    return T;
}

void Preorder(AVLTree T)//前序遍历方便看树的结果
{
    if(T==NULL) return ;
    cout<data<<"\t"<height<lchild);
    Preorder(T->rchild);
}

 void Inorder(AVLTree T)//中序遍历方便看树的结果
{
    if(T==NULL) return ;
    Inorder(T->lchild);
    cout<data<<"\t"<height<rchild);
}

 void Posorder(AVLTree T)//后序遍历方便看树的结果
{
    if(T==NULL) return ;
    Posorder(T->lchild);
    Posorder(T->rchild);
    cout<data<<"\t"<height<>n;
    for(int i=0;i>x;
        T=Insert(T,x);
    }
    return T;
}
int main()
{
    int x;
    AVLTree root=NULL;
    root=Empty(root);
    CreateAVL(root);
    show(root);
    cin>>x;
    root=Delete(root,x);
    show(root);
    return 0;
}

9.1  二分搜索

#include
#include
using namespace std;
const int M=100;
int x,n,i;
int s[M];

int BinarySearch(int s[],int n,int x){//二分查找非递归算法
   int low=0,high=n-1;  //low指向有序数组的第一个元素,high指向有序数组的最后一个元素
   while(low<=high){
       int middle=(low+high)/2;  //middle为查找范围的中间值
       if(x==s[middle])  //x等于查找范围的中间值,算法结束
          return middle;
       else if(x>s[middle]) //x大于查找范围的中间元素,则从左半部分查找
              low=middle+1;
            else            //x小于查找范围的中间元素,则从右半部分查找
              high=middle-1;
    }
    return -1;
}

int recursionBS(int s[],int x,int low,int high){ //二分查找递归算法
    //low指向数组的第一个元素,high指向数组的最后一个元素
    if(low>high)              //递归结束条件
        return -1;
    int middle=(low+high)/2; //计算middle值(查找范围的中间值)
    if(x==s[middle])        //x等于s[middle],查找成功,算法结束
        return middle;
    else if(x>n;
    cout<<"请依次输入数列中的元素:";
    for(i=0;i>s[i];
    sort(s,s+n); //二分查找的序列必须是有序的,如果无序需要先排序
    cout<<"排序后的数组为:";
    for(i=0;i>x;
    //i=BinarySearch(s,n,x);
    i=recursionBS(s,x,0,n-1);
    if(i==-1)
		cout<<"该数列中没有要查找的元素"<

9.2  深度优先搜索

01Knapsack

#include
using namespace std;
const int M=105;
int i,j,n,W;//n表示n个物品,W表示背包的容量
double w[M],v[M];//w[i] 表示第i个物品的重量,v[i] 表示第i个物品的价值
bool x[M];  //x[i]表示第i个物品是否放入背包
double cw;  //当前重量
double cp;  //当前价值
double bestp;  //当前最优价值
bool bestx[M]; //当前最优解

double Bound(int i){//计算上界(即已装入物品价值+剩余物品的总价值)
    //剩余物品为第i~n种物品
    int rp=0;
    while(i<=n){//依次计算剩余物品的价值
        rp+=v[i];
        i++;
    }
    return cp+rp;
}

void Backtrack(int t){//用于搜索空间数,t表示当前扩展结点在第t层
    if(t>n){//已经到达叶子结点
        for(j=1;j<=n;j++)
            bestx[j]=x[j];
        bestp=cp;//保存当前最优解
        return ;
    }
    if(cw+w[t]<=W){//如果满足约束条件则搜索左子树
        x[t]=1;
        cw+=w[t];
        cp+=v[t];
        Backtrack(t+1);
        cw-=w[t];
        cp-=v[t];
    }
    if(Bound(t+1)>bestp){//如果满足限界条件则搜索右子树
        x[t]=0;
        Backtrack(t+1);
    }
}

void Knapsack(double W, int n){
    cw=0;//初始化当前放入背包的物品重量为0
    cp=0; //初始化当前放入背包的物品价值为0
    bestp=0; //初始化当前最优值为0
    double sumw=0.0; //用来统计所有物品的总重量
    double sumv=0.0; //用来统计所有物品的总价值
    for(i=1;i<=n;i++){
        sumv+=v[i];
        sumw+=w[i];
    }
    if(sumw<=W){
        bestp=sumv;
        cout<<"放入背包的物品最大价值为: "<>n>>W;
    cout<<"请依次输入每个物品的重量w和价值v,用空格分开:"<>w[i]>>v[i];
    Knapsack(W,n);
    return 0;
}
/*测试数据
4 10
2 6
5 3
4 5
2 4
*/

 01Knapsack_2

#include
#include//sort函数需要该头文件 
using namespace std;
const int M=105;
int i,j,n,W;//n表示n个物品,W表示背包的容量
double w[M],v[M];//w[i] 表示第i个物品的重量,v[i] 表示第i个物品的价值
bool x[M];  //x[i]表示第i个物品是否放入背包
double cw;   //当前重量
double cp;   //当前价值
double bestp;  //当前最优价值
bool bestx[M]; //当前最优解

double Bound(int i){//计算上界(即将剩余物品装满剩余的背包容量时所能获得的最大价值)
    //i表示剩余物品为第i~n种物品
    double cleft=W-cw;//剩余容量
    double brp=0.0;
    while(i<=n&&w[i]n){//已经到达叶子结点
        for(j=1;j<=n;j++)
            bestx[j]=x[j];
        bestp=cp;//保存当前最优解
        return ;
    }
    if(cw+w[t]<=W){//如果满足限制条件则搜索左子树
        x[t]=1;
        cw+=w[t];
        cp+=v[t];
        Backtrack(t+1);
        cw-=w[t];
        cp-=v[t];
    }
    if(Bound(t+1)>bestp){//如果满足限制条件则搜索右子树
        x[t]=0;
        Backtrack(t+1);
    }
}

struct Object{//定义物品结构体,包含物品序号和单位重量价值
    int id; //物品序号
    double d;//单位重量价值
};

bool cmp(Object a1,Object a2){//按照物品单位重量价值由大到小排序
    return a1.d>a2.d;
}

void Knapsack(int W,int n){
    double sumw=0; //用来统计所有物品的总重量
    double sumv=0; //用来统计所有物品的总价值
    Object Q[n];   //物品结构体类型,用于按单位重量价值(价值/重量比)排序
    double a[n+1],b[n+1];//辅助数组,用于把排序后的重量和价值赋值给原来的重量价值数组
    for(i=1;i<=n;i++){
        Q[i-1].id=i;
        Q[i-1].d=1.0*v[i]/w[i];
        sumv+=v[i];
        sumw+=w[i];
    }
    if(sumw<=W){
        bestp=sumv;
        cout<<"放入背包的物品最大价值为: "<>n>>W;
    cout<<"请依次输入每个物品的重量w和价值v,用空格分开:"<>w[i]>>v[i];
    Knapsack(W,n);
    return 0;
}
/*测试数据
4 10
2 6
5 3
4 5
2 4
*/

 permutation

#include//1..n的全排列
#define MX 50
using namespace std;
int x[MX];  //解分量
int n;

void myarray(int t){
    if(t>n){
        for(int i=1;i<=n;i++) // 输出排列
            cout<>n;
    for(int i=1;i<=n;i++) //初始化
       x[i]=i;
    myarray(1);
    return 0;
}

 queen

//program 5-4
#include
#include   //求绝对值函数需要引入该头文件
#define M 105
using namespace std;

int n;//n表示n个皇后
int x[M];  //x[i]表示第i个皇后放置在第i行第x[i]列
long long countn;    //countn表示n皇后问题可行解的个数

bool Place(int t) //判断第t个皇后能否放置在第i个位置
{
    bool ok=true;
    for(int j=1;jn)  //如果当前位置为n,则表示已经找到了问题的一个解
    {
        countn++;
        for(int i=1; i<=n;i++) //打印选择的路径
          cout<>n;
    countn=0;
    Backtrack(1);
    cout <<"答案的个数是:"<

 9.3  广度优先搜索

01Knapsack

#include
#include
#include
#include
#include
using namespace std;
const int N=10;
bool bestx[N];
//定义结点。每个节点来记录当前的解。
struct Node{
    int cp,rp; //cp为当前装入背包的物品总价值,rp为剩余物品的总价值
    int rw; //剩余容量
    int id; //物品号
    bool x[N];//解向量
    Node(){}
    Node(int _cp,int _rp,int _rw,int _id){
        cp=_cp;
        rp=_rp;
        rw=_rw;
        id=_id;
        memset(x,0,sizeof(x));//解向量初始化为0
    }
};

struct Goods{//物品
    int weight;//重量 
    int value;//价值 
}goods[N];

int bestp,W,n,sumw,sumv;
/*
  bestp用来记录最优解
  W为背包最大容量。
  n为物品的个数。
  sumw为所有物品的总重量。
  sumv为所有物品的总价值。
*/

int bfs(){//队列式分支限界法 
    int t,tcp,trp,trw;//当前处理的物品序号t,装入背包物品价值tcp,剩余容量trw
    queue q; //创建一个普通队列(先进先出)
    q.push(Node(0,sumv,W,1)); //压入一个初始节点
    while(!q.empty()){
        Node livenode,lchild,rchild;//定义三个结点型变量
        livenode=q.front();//取出队头元素作为当前扩展结点livenode
        q.pop(); //队头元素出队
        t=livenode.id;//当前处理的物品序号
        // 搜到最后一个物品的时候不需要往下搜索
        // 如果当前的背包没有剩余容量(已经装满)了,不再扩展
        if(t>n||livenode.rw==0){
            if(livenode.cp>=bestp){//更新最优解和最优值
				for(int i=1;i<=n;i++)
					bestx[i]=livenode.x[i];
              bestp=livenode.cp;
            }
            continue;
        }
        if(livenode.cp+livenode.rp=goods[t].weight){ //扩展左孩子,满足约束条件,可以放入背包
            lchild.rw=trw-goods[t].weight;
            lchild.cp=tcp+goods[t].value;
            lchild=Node(lchild.cp,trp,lchild.rw,t+1);
            for(int i=1;ibestp)//比最优值大才更新
               bestp=lchild.cp;
            q.push(lchild);//左孩子入队
        }
        if(tcp+trp>=bestp){//扩展右孩子,满足限界条件,不放入背包
            rchild=Node(tcp,trp,trw,t+1);
            for(int i=1;i>n>>W;//输入物品的个数和背包的容量
    bestp=0; //bestv用来记录最优解
    sumw=0; //sumw为所有物品的总重量。
    sumv=0;  //sumv为所有物品的总价值
    for(int i=1;i<=n;i++){//输入每个物品的重量和价值,用空格分开
        cin>>goods[i].weight>>goods[i].value;//输入第i件物品的重量和价值。
        sumw+=goods[i].weight;
        sumv+=goods[i].value;
    }
    if(sumw<=W){
        bestp=sumv;
        cout<<"放入背包的物品最大价值为: "<

 01Knapsack_2

#include
#include
#include
#include
#include
using namespace std;
const int N=10;
bool bestx[N]; //记录最优解
int w[N],v[N];//辅助数组,用于存储排序后的重量和价值

struct Node{//定义结点,记录当前结点的解信息
    int cp; //已装入背包的物品价值
    double up; //价值上界
    int rw; //背包剩余容量
    int id; //物品号
    bool x[N];
    Node() {}
    Node(int _cp,double _up,int _rw,int _id){
        cp=_cp;
        up=_up;
        rw=_rw;
        id=_id;
        memset(x, 0, sizeof(x));
    }
};

struct Goods{ //物品结构体
    int weight;//重量
    int value;//价值
}goods[N];

struct Object{//辅助物品结构体,用于按单位重量价值(价值/重量比)排序
    int id; //序号
    double d;//单位重量价值
}S[N];


bool cmp(Object a1,Object a2){//排序优先级,按照物品单位重量价值由大到小排序
    return a1.d>a2.d;
}

bool operator <(const Node &a, const Node &b){//队列优先级。up越大越优先
    return a.up q; //创建一个优先队列
    q.push(Node(0,sumv,W,1));//初始化,根结点加入优先队列
    while(!q.empty()){
        Node livenode, lchild, rchild;//定义三个结点型变量
        livenode=q.top();//取出队头元素作为当前扩展结点livenode
        q.pop(); //队头元素出队
        t=livenode.id;//当前处理的物品序号
        // 搜到最后一个物品的时候不需要往下搜索。
        // 如果当前的背包没有剩余容量(已经装满)了,不再扩展。
        if(t>n||livenode.rw==0){
            if(livenode.cp>=bestp){//更新最优解和最优值
            	for(int i=1;i<=n;i++)
            		bestx[i]=livenode.x[i];
            	bestp=livenode.cp;
            }
            continue;
        }
        if(livenode.up=w[t]){ //扩展左孩子,满足约束条件,可以放入背包
            lchild.cp=tcp+v[t];
            lchild.rw=trw-w[t];
            lchild.id=t+1;
            tup=Bound(lchild); //计算左孩子上界
            lchild=Node(lchild.cp,tup,lchild.rw,lchild.id);
            for(int i=1;i<=n;i++)//复制以前的解向量
            	lchild.x[i]=livenode.x[i];
            lchild.x[t]=true;
            if(lchild.cp>bestp)//比最优值大才更新
            	bestp=lchild.cp;
            q.push(lchild);//左孩子入队
        }
        rchild.cp=tcp;
        rchild.rw=trw;
        rchild.id=t+1;
        tup=Bound(rchild);//计算右孩子上界
        if(tup>=bestp){//扩展右孩子,满足限界条件,不放入
            rchild=Node(tcp,tup,trw,t+1);
            for(int i=1;i<=n;i++)//复制以前的解向量
            	rchild.x[i]=livenode.x[i];
            rchild.x[t]=false;
            q.push(rchild);//右孩子入队
          }
    }
    return bestp;//返回最优值。
}

int main(){
    bestp=0; //bestv用来记录最优解
    sumw=0; //sumw为所有物品的总重量。
    sumv=0;   //sumv为所有物品的总价值
    cin>>n>>W;
    for(int i=1;i<=n;i++){
        cin>>goods[i].weight>>goods[i].value;//输入第i件物品的重量和价值。
        sumw+=goods[i].weight;
        sumv+=goods[i].value;
        S[i-1].id=i;
        S[i-1].d=1.0*goods[i].value/goods[i].weight;
    }
    if(sumw<=W){
        bestp=sumv;
        cout<<"放入背包的物品最大价值为: "<

你可能感兴趣的:(算法,算法,c++,图论)