数据结构课程设计(已完结)

目录

 报数问题

迷宫问题

 拓扑排序

散列文件的插入、删除和查找

二叉排序树和二叉平衡树:

_____________________________________________________________________________

迷宫代码出bug了我改了下只改了最终代码了把迷宫上的走的路线改成了从2开始了

大家能看懂就好

 报数问题

其实就是约瑟夫环用但循环列表来实现

忽然发现我们学校的并不是约瑟夫环

题目如下:

9、报数问题

问题描述:有n个小朋友围成一圈玩游戏,小朋友从1n编号,2号小朋友坐在1号小朋友的顺时针方向,3号小朋友坐在2号小朋友的顺时针方向,……,1号小朋友坐在n号小朋友的顺时针方向。
  游戏开始,从1号小朋友开始顺时针报数,接下来每个小朋友的报数是上一个小朋友报的数加1。若一个小朋友报的数为k的倍数或其末位数(即数的个位)为k,则该小朋友被淘汰出局,不再参加以后的报数。当游戏中只剩下一个小朋友时,该小朋友获胜。
  例如,当n=5, k=2时:
  1号小朋友报数1
  2号小朋友报数2淘汰;
  3号小朋友报数3
  4号小朋友报数4淘汰;
  5号小朋友报数5
  1号小朋友报数6淘汰;
  3号小朋友报数7
  5号小朋友报数8淘汰;
  3号小朋友获胜。
  给定nk,请问最后获胜的小朋友编号为多少?

输入格式

  输入一行,包括两个整数nk,意义如题目所述。

输出格式

  输出一行,包含一个整数,表示获胜的小朋友编号。

样例输入

5 2

样例输出

3

样例输入

7 3

样例输出

4

数据规模和约定

对于所有评测用例,1  n  10001  k  9
要求:利用单向循环链表存储结构模拟此过程。

#include <iostream>
#include <stdio.h>
using namespace std;
int N, K; // 1<=N<=1000 1<=K<=9
typedef struct Node
{
    int data;
    struct Node *next;
} Node, *LNode;
void creat_list(LNode &H)
{
    LNode p, q;
    q = H;
    int i = 0;
    int x; //尾插法
    for (int i = 0; i < N; i++)
    {
        p = new Node;
        p->data = i+1;
        p->next = NULL;
        q->next = p;
        q = p;
    }
    p->next = H;
}
void print_list(LNode &H)
{
    LNode p = H->next;
    while (p != H)
    {
        cout << p->data << " ";
        p = p->next;
    }
}
void win_put(LNode &H){
    int count=1,key=0;LNode p=H->next;LNode q=H;//count报数计数器
    while(N-key!=1){
        if(count%K==0||count%10==K){
            LNode del;
            del=p;
            p=p->next;
            q->next=p;
            free(del);
            key++;//人数计数器
        }
        else{
            p=p->next;
            q=q->next;
        }
        if(p==H){
            p=H->next;
            q=H;
        }
        count++;
    }
    cout<<p->data;
}
int main()
{
    cin >> N >> K;
    LNode H;
    H = new Node;
    H->next = NULL;
    creat_list(H);
    //print_list(H);
    win_put(H);
}

迷宫问题

主要用一个二维数组来表现迷宫用栈来记录路径和存放路径

 第一步结构体:

const int MAXLENGTH = 50;
typedef int MazeType[MAXLENGTH][MAXLENGTH]; // 迷宫数组[行][列]
MazeType m;                                 //声明一个全局迷宫对象m
typedef struct                              //坐标
{
    int x;
    int y;
} PosType; //坐标结构体
typedef struct
{
    int ord;      //通道块在路径上的“序号”
    PosType seat; //通道块在迷宫中的“坐标位置”
    int di;       //从从此通道块走向下一通道块的“方向”
} SElemType;      //栈的元素类型
typedef struct
{
    SElemType *base; //栈底指针
    SElemType *top;  //栈顶指针
    int stacksize;   //栈的大小
} Stack;
//用的是顺序栈

第二步是栈的一些函数:

int  InitStack(Stack &S)

// 构造一个空栈S

int Push(Stack &S, SElemType e)  

  //入栈

int Pop(Stack &S, SElemType &e)

//出栈,移除当前栈顶元素

int StackEmpty(Stack S)

//检测是否为空栈
int  InitStack(Stack &S) // 构造一个空栈S
{
    S.base=new SElemType[MAXSIZE];
    S.top = S.base;
    S.stacksize = MAXSIZE;
    return OK;
}

int Push(Stack &S, SElemType e)     //入栈
{                                      
    if(S.top-S.base==S.stacksize){
        return ERROR;
    }
    *(S.top)++ = e;
    return OK;
}

int Pop(Stack &S, SElemType &e) //出栈,移除当前栈顶元素
{
    if (S.top == S.base)
        return ERROR;
    e = *--S.top;
    return OK;
}

int StackEmpty(Stack S) //检测是否为空栈
{
    if (S.top == S.base)
        return OK;
    else
        return ERROR;
}

第三步输出迷宫(0代表的是墙1代表的是通道).

void Print(int x, int y) // 输出迷宫图,0表示墙,1表示通路
{
    int i, j;
    for (i = 0; i < x; i++)
    {
        for (j = 0; j < y; j++)
            printf("%3d", m[i][j]);
        printf("\n");
    }
}

第四步在迷宫移动时的一些函数 

int Pass(PosType b)

看看b点能否通过

void FootPrint(PosType a)

把他的序号变成足迹

PosType NextPos(PosType c, int di)

根据当前位置及移动方向返回下一位置

void MarkPrint(PosType b)

死点(就是怎么都不能走的点)

int MazePath(PosType start, PosType end)

迷宫的从start怎么走到end的函数
int Pass(PosType b) // 当迷宫m的b点的序号为1(可通过路径)
{
    if (m[b.X][b.Y] == 1)
        return 1;
    else
        return 0;
}
void FootPrint(PosType a) // 使迷宫m的a点的序号变为足迹(curstep)
{
    m[a.X][a.Y] = curstep;
}
PosType NextPos(PosType c, int di) // 根据当前位置及移动方向,返回下一位置
{
    PosType dir[4] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // {行增量,列增量}
    //方向依次为上右下左
    c.X += dir[di].X;
    c.Y += dir[di].Y;
    return c;
}
void MarkPrint(PosType b)
{
    m[b.X][b.Y] = -1; // 使迷宫m的b点的序号变为-1(不能通过的路径)
}
int MazePath(PosType start, PosType end) // 若迷宫maze中存在从入口start到出口end的通道,则求得一条存放在栈中(从栈底到栈顶),并返回TRUE;否则返回FALSE
{
    Snode S;
    PosType curpos;
    SElemType e;
    InitStack(S);
    curpos = start; //把入口设置为当前位置
    do//应为栈一开始是空的所以 do while
    {
        if (Pass(curpos))
        {                      // 当前位置可以通过,即是未曾走到过的通道块
            FootPrint(curpos); // 留下足迹
            e.ord = curstep;
            e.seat.X = curpos.X;
            e.seat.Y = curpos.Y;//当前位置
            e.di = 0;
            Push(S, e);                                 // 入栈当前位置及状态
            curstep++;                                  // 足迹加1
            if (curpos.X == end.X && curpos.Y == end.Y) // 到达终点(出口)
                return 1;
            curpos = NextPos(curpos, e.di); //将当前位置变为e.di方向上的临近通道块
        }
        else
        { // 当前位置不能通过
            if (!StackEmpty(S))
            {
                Pop(S, e); // 退栈到前一位置
                curstep--;//走的路径长度
                while (e.di == 3 && !StackEmpty(S)) // 前一位置处于最后一个方向(北),即当前位置的四周都无法通过
                {
                    MarkPrint(e.seat); // 留下不能通过的标记(-1)
                    Pop(S, e);         // 退回一步
                    curstep--;
                }
                if (e.di < 3) // 没到最后一个方向(北)
                {
                    e.di++; // 换下一个方向探索
                    Push(S, e);
                    curstep++;
                    curpos = NextPos(e.seat, e.di); // 设定当前位置是该新方向上的相邻块
                }
            }
        }
    } while (!StackEmpty(S));
    return 0;
}

第五步是主函数

int main()
{
    int X, Y, i, j, n;
    cout << "输入迷宫的行数,列数:" << endl;
    cin >> X >> Y;
    for (i = 0; i < Y; i++) // 定义上下边的墙值为0
    {
        m[0][i] = 0;     //第一行为0
        m[X - 1][i] = 0; //最后一行为0
    }
    for (j = 1; j < X - 1; j++) //左右两边列为0
    {
        m[j][0] = 0;
        m[j][Y - 1] = 0;
    }
    for (i = 1; i < X - 1; i++) //定义所有内墙值为1(即通路)
        for (j = 1; j < Y - 1; j++)
            m[i][j] = 1;
    cout << "请输入迷宫的内墙数:" << endl;
    cin >> n;
    for (i = 0; i < n; i++)
    {
        int x, y; //输入内墙的坐标值,以左上角坐标为(1,1)计算
        cout << "输入第" << i + 1 << "个墙的位置" << endl;
        cin >> x >> y;
        m[x][y] = 0;
    }
    PosType a, b;
    a.X = 1;
    a.Y = 1;
    b.X = 8;
    b.Y = 8;
    MazePath(a, b);
    Print(X, Y);
}

最终代码:

#include <iostream>
#include <stdio.h>
#include <fstream>
using namespace std;
const int MAXLENGTH = 25;
typedef int MazeType[MAXLENGTH][MAXLENGTH]; // 迷宫数组[行][列]
const int MAXSIZE = 576;
const int OK = 1;
const int ERROR = 0;
MazeType m;      //声明一个全局迷宫对象m
int curstep = 2; //走的路径长度
typedef struct   //坐标
{
    int X;
    int Y;
} PosType; //坐标结构体
typedef struct
{
    int ord;      //通道块在路径上的“序号”
    PosType seat; //通道块在迷宫中的“坐标位置”
    int di;       //从从此通道块走向下一通道块的“方向”
} SElemType;      //栈的元素类型
typedef struct
{
    SElemType *base;
    SElemType *top;
    int stacksize;
} Stack;
int InitStack(Stack &S) // 构造一个空栈S
{
    S.base = new SElemType[MAXSIZE];
    S.top = S.base;
    S.stacksize = MAXSIZE;
    return OK;
}

int Push(Stack &S, SElemType e) //入栈
{
    if (S.top - S.base == S.stacksize)
    {
        return ERROR;
    }
    *(S.top)++ = e;
    return OK;
}

int Pop(Stack &S, SElemType &e) //出栈,移除当前栈顶元素
{
    if (S.top == S.base)
        return ERROR;
    e = *--S.top;
    return OK;
}

int StackEmpty(Stack S) //检测是否为空栈
{
    if (S.top == S.base)
        return OK;
    else
        return ERROR;
}
int Pass(PosType b) // 当迷宫m的b点的序号为1(可通过路径)
{
    if (m[b.X][b.Y] == 1)
        return OK;
    else
        return ERROR;
}
void FootPrint(PosType &a) // 使迷宫m的a点的序号变为足迹(curstep)
{
    m[a.X][a.Y] = curstep;
}
PosType NextPos(PosType c, int di) // 根据当前位置及移动方向,返回下一位置
{
    PosType dir[4] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // {行增量,列增量}
    //方向依次为上右下左
    c.X += dir[di].X;
    c.Y += dir[di].Y;
    return c;
}
void MarkPrint(PosType b)
{
    m[b.X][b.Y] = -1; // 使迷宫m的b点的序号变为-1(不能通过的路径)
}
int MazePath(PosType start, PosType end) // 若迷宫maze中存在从入口start到出口end的通道,则求得一条存放在栈中(从栈底到栈顶)
{
    Stack S;
    PosType curpos;
    SElemType e;
    InitStack(S);
    curpos = start; //把入口设置为当前位置
    do              //应为栈一开始是空的所以 do while
    {
        if (Pass(curpos))
        {                      // 当前位置可以通过,即是未曾走到过的通道块
            FootPrint(curpos); // 留下足迹
            e.ord = curstep;
            e.seat.X = curpos.X;
            e.seat.Y = curpos.Y; //当前位置
            e.di = 0;
            Push(S, e);                                 // 入栈当前位置及状态
            curstep++;                                  // 足迹加1
            if (curpos.X == end.X && curpos.Y == end.Y) // 到达终点(出口)
                return OK;
            curpos = NextPos(curpos, e.di); //将当前位置变为e.di方向上的临近通道块
        }
        else
        { // 当前位置不能通过
            if (!StackEmpty(S))
            {
                Pop(S, e);                          // 退栈到前一位置
                curstep--;                          //走的路径长度
                while (e.di == 3 && !StackEmpty(S)) // 前一位置处于最后一个方向(北),即当前位置的四周都无法通过
                {
                    MarkPrint(e.seat); // 留下不能通过的标记(-1)
                    Pop(S, e);         // 退回一步
                    curstep--;
                }
                if (e.di < 3) // 没到最后一个方向(北)
                {
                    e.di++; // 换下一个方向探索
                    Push(S, e);
                    curstep++;
                    curpos = NextPos(e.seat, e.di); // 设定当前位置是该新方向上的相邻块
                }
            }
        }
    } while (!StackEmpty(S));
    return ERROR;
}
void Print(int x, int y) // 输出迷宫图,0表示墙,1表示通路
{
    int i, j;
    for (i = 0; i < x; i++)
    {
        for (j = 0; j < y; j++)
            printf("%3d", m[i][j]);
        printf("\n");
    }
}
#define    readDataPath "C:\\Users\\yu\\Desktop\\MAze.txt"
int main()
{
    int X, Y, i, j, n;
    cin >> X >> Y;
    FILE *fp = fopen(readDataPath, "r"); //打开文件
    for (i = 0; i < X ;i++)
    {
        for (j = 0; j < Y; j++)
        {
            fscanf(fp, "%d", &m[i][j]); /*每次读取一个数,fscanf函数遇到空格或者换行结束*/
        }
        fscanf(fp, "\n");
    }
    fclose(fp);
    PosType a, b;
    a.X = 1;
    a.Y = 1;
    b.X = 8;
    b.Y = 8;
    if (MazePath(a, b))
    {
            Print(X, Y);
    }
    else
    {
        cout << "No find" << endl;
    }
}

我把迷宫图形保存到了文件里了

 拓扑排序

特别简单不多作介绍了

利用有向图邻接表来实现

数据是:

 输出结果是:v9 v10 v11 v6 v1 v4 v2 v3 v5 v7  v8 v12 

#include <iostream>
#include <algorithm>
#include <queue>
#include<cstring>
#include<stack>
using namespace std;
#define MAXN 105
typedef struct ArcNode{
    int adjvex;
    struct ArcNode *nextarc;
}ArcNode;
typedef struct VNode{
    int data;
    ArcNode *firstarc;
}VNode,AdjList[MAXN];
typedef struct{
    AdjList Vertices;
    int vexnum,arcnum;
}ALGraph;
void Creat_UDG(ALGraph &G)//有向图
{
    cin>>G.vexnum>>G.arcnum;
    for(int i=1;i<=G.vexnum;i++){
        cin>>G.Vertices[i].data;
        G.Vertices[i].firstarc=NULL;
    }
    
    
    for(int i=1;i<=G.arcnum;i++)
    {    int x,y;
        cin>>x;cin>>y;

        ArcNode *p1=new ArcNode;
        ArcNode *p2=new ArcNode;
        
        p1->adjvex=y;
        p1->nextarc=G.Vertices[x].firstarc;//应为他是有向图
        G.Vertices[x].firstarc=p1;
    }
} 
int in[100],out[100];
void info(ALGraph G)
{
    
    for(int i=1;i<=G.vexnum;i++)
    {
        ArcNode *p=G.Vertices[i].firstarc;
        while(p){
            out[i]++;
            in[p->adjvex]++;
            p=p->nextarc;
        }
    }
}
int Topologicallsort(ALGraph G,int topo[]){
    stack<int >S;
    info(G);
    for(int i=1;i<=G.vexnum;i++){
        if(in[i]==0){
            S.push(i);//将入度为0的全部押入
        }
    }
    int m=0,i;
    while(!S.empty()){
        i=S.top();
        S.pop();
        topo[m]=i;
        m++;
        ArcNode *p=G.Vertices[i].firstarc;
        while(p){
            in[p->adjvex]--;
            if(in[p->adjvex]==0){
                S.push(p->adjvex);
            }
            p=p->nextarc;
        }
    }
    if(m<G.vexnum) {
        return 0;
    }
    else{
        return 1;
    }
    
}
int main()
{
    ALGraph G;
    Creat_UDG(G);//创建了一个有向图;
    int topo[G.vexnum+1];
    Topologicallsort(G,topo);
    for(int i=0;i<G.vexnum;i++){
        cout<<"v"<<topo[i]<<" ";
    }
}

散列文件的插入、删除和查找

只是一个大致实现等我有空在慢慢优化

效果如图:

#include <iostream>
#include <stdio.h>
using namespace std;
const int MAXSIZE = 1e5 + 5;
typedef struct FLNode
{
    int data;
    struct FLNode *next;
} FLNode;
FILE *fp;
FLNode HT[MAXSIZE]; //散列表文件
void Init()
{
    if ((fp = fopen("hash.txt", "r")) == NULL) //读散列主文件
    {
        cout << "Not find" << endl;
    }
    int key, h;
    for (int i = 0; i < 13; i++) //单链表的数量定为13
    {
        HT[i].next = NULL;
    }
    while (!feof(fp))
    {
        fscanf(fp, "%d ", &key);
        h = key % 13;
        FLNode *q = new FLNode;
        q->data = key;
        q->next = HT[h].next;
        HT[h].next = q;
    }
    fclose(fp);
    return;
}
void Insert(int &key)
{ //向散列文件中插入数据
    int h;
    h = key % 13;
    FLNode *q = new FLNode;
    q->data = key;
    q->next = HT[h].next;
    HT[h].next = q;
    if ((fp = fopen("hash.txt", "w")) == NULL) //重新覆盖原有数据
    {
        cout << "not find" << endl;
    }
    for (int i = 0; i < 13; i++)
    {
        FLNode *p = HT[i].next;
        while (p)
        {
            fprintf(fp, "%d ", p->data); //写入文件中去
            p = p->next;
        }
        fprintf(fp, "\n");
    }
    fclose(fp);
    return;
}
void Search(int key)
{
    int h;
    h = key % 13;
    FLNode *p = HT[h].next;
    while (p)
    {
        if (p->data == key)
        {
            cout << "Succefully Find !" << key << endl;
            break;
        }
        p = p->next;
    }
    if (!p)
    {
        cout << "Not Find" << key << endl;
    }
}
void Delete(int key)
{
    int h;
    h = key % 13;
    FLNode *p, *q;
    p = &HT[h];
    q = HT[h].next;
    while (q)
    {
        if (q->data == key)
        {
            p->next = q->next;
            cout << "Succefully delete!" << endl;
            break;
        }
        p = p->next;
        q = q->next;
    }
    if (!q)
        cout << "Not find,can not delete" << endl;
    else
    {
        if ((fp = fopen("hash.txt", "w")) == NULL)
        {
            cout << "not find" << endl;
        }
        for (int i = 0; i < 13; i++)
        {
            FLNode *p = HT[i].next;
            while (p)
            {
                fprintf(fp, "%d ", p->data);
                p = p->next;
            }
            fprintf(fp, "\n");
        }
        fclose(fp);
    }
    return;
}
int main()
{
    int key;
    if ((fp = fopen("hash.txt", "w")) == NULL)
    {
        cout << "not find" << endl;
    }
    cin >> key;
    while (key != 0)
    {
        fprintf(fp, "%d ",key);
        cin >> key;
    }
    fclose(fp);
    Init();
    cout << "Insert data into hash file:" << endl;
    cin >> key;
    Insert(key);
    cout << "Remove element from hash file:" << endl;
    cin >> key;
    Delete(key);
    cout << "Find data from hash file:" << endl;
    cin >> key;
    Search(key);
}

二叉排序树和二叉平衡树:

编程实现二叉排序树的创建、插入、删除和查询

编程实现二叉平衡树的创建、插入、删除和查询

最后一个了做完就完事了感觉就是对基础结构的理解更深了一点吧

 二叉排序树:

//二叉排序树的插入创建删除和查询
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
typedef struct BSTNOde
{
    int data;
    struct BSTNOde *lchild, *rchild;
} STNOde, *BSTree; //二叉排序树的结构定义
FILE *fp;
BSTree SearchBST(BSTree T, int &key)
{
    //二叉排序树中的查找
    if ((!T) || key == T->data)
    {
        if(!T){

            cout<<"Not find"<<endl;
        }
        else{
            cout<<"Find"<<T->data<<endl;
        }
        return T;
    }
    else if (key < T->data)
    {
        return (SearchBST(T->lchild, key));
    }
    else
    {
        return (SearchBST(T->rchild, key));
}
}

void Insert(BSTree &T, int &key)
{
    if (!T) //当T是空的时候
    {
        BSTree s = new BSTNOde;
        s->data = key;
        s->lchild = s->rchild = NULL;
        T = s;
    }
    else if (key < T->data)
    {
        Insert(T->lchild, key);
    }
    else
    {
        Insert(T->rchild, key);
    }
    // O(log2(n))
} //永远插入的位置都是叶子
void CreatBST(BSTree &T)
{
    fp = fopen("tree.txt", "r");
    T = NULL;
    int e;
    while (!feof(fp))
    { //结束标志
        fscanf(fp, "%d", &e);
        Insert(T, e);
    }
    // O(n*log2(n))
}
void DeleteBST(BSTree &T,int key) {
    BSTree p=T,f=NULL;
    while(p){
        if(p->data==key){
            break;
        }
        f=p;//f记录的是p的双亲
        if(p->data>key){
            p=p->lchild;
        }
        if(p->data<=key){
            p=p->rchild;
        }
    }
    if(!p){
        cout<<"Not find!";
        return ;
    }
    BSTree q=p;//找到了那个被删除的值并且把它付给p
    if(p->lchild&&p->rchild){//他的左右结点都存在时
        BSTree s=p->lchild;
        while(s->rchild){
            q=s;//r是s的双亲
            s=s->rchild;
        }
        p->data=s->data;//将s的值给p接下来只需要处理p
        if(q!=p){
        //就是s双亲不是p的时侯
        q->rchild=s->lchild;            
        }
        else{
            q->lchild=s->lchild;
        }
        delete s;
        return ;
    }
    else if(!p->lchild){
        p=p->rchild;
    }
    else if(!p->rchild){
        p=p->lchild;
    }
    if(!f){
        T=p;
    }
    else if(q==f->lchild){
        f->lchild=p;
    }
    else{
        f->rchild=p;
    }
    delete q;
}
void Print(BSTree T)
{ //中序遍历
    if (!T)
    {
        return;
    }
    Print(T->lchild);
    cout << T->data << " ";
    Print(T->rchild);
}
int main()
{
    BSTree T;
    CreatBST(T);
    int x, y, z;
    Print(T); //中序遍历得到一个有序的序列
    cout <<endl<< "Please enter a value to insert"<<endl;
    cin >> x;
    Insert(T, x);
    Print(T); //中序遍历得到一个有序的序列
    cout<<endl << "Please enter a value to find:"<<endl;
    cin >> y;
    SearchBST(T, y);
    cout <<endl<< "Please enter a value to delete:"<<endl;
    cin >> z;
    DeleteBST(T, z);
}

二叉平衡树:

#include <bits/stdc++.h>
#define LH 1  //左高
#define EH 0  //等高
#define RH -1 //右高
//二叉平衡树
using namespace std;
int a[105];
typedef struct BTnode
{
    int data;
    int bf;
    BTnode *lchild, *rchild;
} BTnode, *BTtree;

int Depth(BTtree T)
{
    if (!T)
        return 0;
    else
    {
        int m = Depth(T->lchild);
        int n = Depth(T->rchild);
        if (m > n)
        {
            return m + 1;
        }
        else
        {
            return n + 1;
        }
    }
}

void R_Rotate(BTtree *T) //右旋
{
    BTtree L;
    L = (*T)->lchild;
    (*T)->lchild = L->rchild;
    L->rchild = (*T);
    *T = L;
}
void L_Rotate(BTtree *T) //左旋
{
    BTtree R;
    R = (*T)->rchild;
    (*T)->rchild = R->lchild;
    R->lchild = (*T);
    *T = R;
}

void LeftBalance(BTtree *T)/左平衡
{
    BTtree L, Lr;
    L = (*T)->lchild;
    switch (L->bf)
    {
    case LH: // LL
        (*T)->bf = L->bf = EH;
        R_Rotate(T);
        break;
    case RH: // LR
        Lr = L->rchild;
        switch (Lr->bf)
        {
        case LH: //左高
            (*T)->bf = RH;
            L->bf = EH;
            break;
        case EH: //平衡
            (*T)->bf = L->bf = EH;
            break;
        case RH: //右高
            (*T)->bf = EH;
            L->bf = LH;
            break;
        }
        Lr->bf = EH;
        L_Rotate(&(*T)->lchild); //左子树左旋处理
        R_Rotate(T);             //右旋处理
        break;
    case EH: //特殊情况4,这种情况在添加时不可能出现,只在移除时可能出现,旋转之后整体树高不变
        L->bf = RH;
        (*T)->bf = LH;
        R_Rotate(T);
        break;
    }
}
void RightBalance(BTtree *T)//右平衡
{
    BTtree R, Rl;
    R = (*T)->rchild;
    switch (R->bf)
    {
    case RH: // RR
        (*T)->bf = R->bf = EH;
        L_Rotate(T);
        break;
    case LH: // RL
        Rl = R->lchild;
        switch (Rl->bf)
        {
        case LH:
            (*T)->bf = EH;
            R->bf = RH;
            break;
        case EH:
            (*T)->bf = R->bf = EH;
            break;
        case RH:
            (*T)->bf = LH;
            R->bf = EH;
            break;
        }
        Rl->bf = EH;
        R_Rotate(&(*T)->rchild); //右子树右旋处理
        L_Rotate(T);             //左旋
        break;
    case EH: //特殊情况4,这种情况在添加时不可能出现,只在移除时可能出现,旋转之后整体树高不变
        R->bf = LH;
        (*T)->bf = RH;
        L_Rotate(T);
        break;
    }
}

BTtree creatBTtree()
{
    BTtree bt = NULL;
    return bt;
}

void InOrderTraverseBTtree(BTtree T) //中序遍历
{
    if (T)
    {
        InOrderTraverseBTtree(T->lchild);
        printf("(%d,%d) ", T->bf, T->data);
        InOrderTraverseBTtree(T->rchild);
    }
    else
    {
        return;
    }
}

int InsertAVL(BTtree *T, int e, int *tall) //插入函数
{
    if (!*T)
    {
        *T = new BTnode;
        (*T)->data = e;
        (*T)->lchild = (*T)->rchild = NULL;
        (*T)->bf = EH;
        *tall = 1;
    }
    else
    {
        if (e == (*T)->data)
        {
            *tall = 0;
            return 0;
        }
        else if (e < (*T)->data) //左子树中寻找
        {
            if (!InsertAVL(&(*T)->lchild, e, tall))
            {
                return 0;
            }
            if (*tall)
            {
                switch ((*T)->bf)
                {
                case LH: // ll
                    LeftBalance(T);
                    *tall = 0;
                    break;
                case EH:
                    (*T)->bf = LH;
                    *tall = 1;
                    break;
                case RH:
                    (*T)->bf = EH;
                    *tall = 0;
                    break;
                }
            }
        }
        else //右子树中寻找
        {
            if (!InsertAVL(&(*T)->rchild, e, tall))
            {
                return 0;
            }
            if (*tall)
            {
                switch ((*T)->bf)
                {
                case LH:
                    (*T)->bf = EH;
                    *tall = 0;
                    break;
                case EH:
                    (*T)->bf = RH;
                    *tall = 1;
                    break;
                case RH:
                    RightBalance(T);
                    *tall = 0;
                    break;
                }
            }
        }
    }
    return 1;
}
int SearchBST(BTtree T, int e, BTtree *f, BTtree *p) //寻找元素是否存在
// T为当前根节点,e为要查找的元素,f为T的父节点,p为找到的元素节点或没找到时的根节点
{
    if (!T) //若树空
    {
        *p = *f;
        return 0;
    }
    else if (T->data == e) //若找到该元素
    {
        *p = T;
        return 1;
    }
    else if (e < T->data) //如果该元素比根节点值小
        return SearchBST(T->lchild, e, &T, p);
    else //如果该元素比根节点值大
        return SearchBST(T->rchild, e, &T, p);
}

int deleteAVL(BTtree &t, BTtree *f, int e, int *shorter)
{
    if (t == NULL)
    {
        return 0;
    }
    else if (t->data == e)
    {
        BTtree q = NULL;
        if (t->lchild == NULL) //左子树为空
        {
            q = t;
            t = t->rchild;
            free(q);
            *shorter = 1;
        }
        else if (t->rchild == NULL) //右子树为空
        {
            q = t;
            t = t->lchild;
            free(q);
            *shorter = 1;
        }
        else //左右子树都存在
        {
            BTtree s = t;
            q = t->lchild;
            while (q->rchild)
            {
                s = q;
                q = q->rchild;
            }
            t->data = q->data;
            deleteAVL(t->lchild, &t, q->data, shorter); //在左子树中递归删除前驱结点
        }
    }
    else if (e < t->data) //左子树中继续查找
    {
        if (!deleteAVL(t->lchild, &t, e, shorter))
        {
            return 0;
        }
        if (*shorter)
        {
            switch (t->bf)
            {
            case LH: //若原来LH,删除左节点,状态变为EH
                t->bf = EH;
                *shorter = 1;
                break;
            case EH: //若原来平衡,删除左节点,状态变为RH
                t->bf = RH;
                *shorter = 0;
                break;
            case RH:
                if (t->rchild->bf == EH)
                    *shorter = 0;
                else
                    *shorter = 1; //若为此情况,树高减一
                RightBalance(&t); //右平衡处理
                break;
            }
        }
    }
    else //右子树中继续查找
    {
        if (!deleteAVL(t->rchild, &t, e, shorter))
        {
            return 0;
        }
        if (*shorter)
        {
            switch (t->bf)
            {
            case LH:
                if (t->lchild->bf == EH) //若为此情况,树高减一
                    *shorter = 0;
                else
                    *shorter = 1;
                LeftBalance(&t); //左平衡处理
                break;
            case EH: //若原来平衡,删除右节点,状态变为LH
                t->bf = LH;
                *shorter = 0;
                break;
            case RH: //若原来RH,删除右节点,状态变为EH
                t->bf = EH;
                *shorter = 1;
                break;
            }
        }
    }
    return 1;
}

int main()
{
    BTtree T, p, f;
    T = creatBTtree();
    int x, n;
    int tall, shorter;
    n = 0;
    printf("请输入你要创建二叉平衡树的数字,输入0表示结束输入:");
    while (~scanf("%d", &x))
    {
        if (!x)
            break;
        a[++n] = x;
    }
    for (int i = 1; i <= n; i++)
    {
        InsertAVL(&T, a[i], &tall);
    }
    printf("中序遍历该二叉平衡树的结果为:");
    InOrderTraverseBTtree(T);
    printf("\n");

    int num;
    printf("请输入你要插入的数字:");
    cin >> num;
    InsertAVL(&T, num, &tall);
    printf("插入该数字后中序遍历该二叉排序树的结果为:");
    InOrderTraverseBTtree(T);
    printf("\n");

    int xx, y;
    printf("请输入你要查询的数字:");
    cin >> xx;
    f = NULL;
    if (SearchBST(T, xx, &f, &p))
    {
        printf("该数存在\n");
    }
    else
    {
        printf("该数不存在\n");
    }

    printf("请输入你要删除的数字:");
    cin >> y;
    f = NULL;
    if (!SearchBST(T, y, &f, &p))
    {
        printf("该数不存在,无法进行删除操作!\n");
    }
    else
    {
        deleteAVL(T, &f, y, &shorter);
        printf("进行删除操作后中序遍历该二叉排序树的结果为:");
        InOrderTraverseBTtree(T);
    }
    printf("平衡二叉树的深度:%d", Depth(T));
    printf("\n");
    return 0;
}
/*
1 5 4 2 6 8 7 9 11 14 13 12 16 19 0
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小李小于

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值