拓扑排序(邻接链表,邻接矩阵,栈,队列)

 

用c写的邻接链表(或邻接矩阵)存储,栈(或队列)实现的拓扑排序。

#include
#include
#define STACK_INIT_SIZE 100
#define VNUM 100
#define STACKINCREMENT 10
#define OVERFLOW 0
#define ERROR 0
#define OK 1
#define MAX_VERTEX_NUM 20
typedef int Status;
typedef char VertexType;
typedef struct ArcNode //邻接链表
{
    int adjvex;//该弧所指向的顶点的位置
    struct ArcNode* nextarc;//指向下一条弧的指针
}ArcNode;
typedef struct VNode
{
    VertexType data;
    ArcNode* firstarc;//指向第一条依附该顶点的弧的指针
}VNode,AdjList[MAX_VERTEX_NUM];
typedef struct {
    AdjList vertices;
    int vexnum, arcnum;
}ALGraph;
typedef struct {
    VertexType vexs[MAX_VERTEX_NUM];
    Status arcs[VNUM][VNUM];
    int vexnum, arcnum;
}MGraph;//邻接矩阵
typedef struct
{
    int* base;
    int* top;
    int stacksize;
}Sqstack;
typedef struct QNode {
    int data;
    struct QNode* next;
}QNode,*QueuePtr;
typedef struct {
    QueuePtr front;
    QueuePtr rear;
}LinkQueue;
Status InitStack(Sqstack *S)
{
    S->base = (int*)malloc(STACK_INIT_SIZE * sizeof(int));
    if (!S->base)
        exit(OVERFLOW);
    S->top = S->base;
    S->stacksize = STACK_INIT_SIZE;
    return OK;
}
Status InitQueue(LinkQueue* Q)
{
    Q->front = Q->rear = (QueuePtr)malloc(sizeof(QNode));
    if (!Q->front)
        exit(OVERFLOW);
    Q->front->next = NULL;
    return OK;
}
Status Push(Sqstack *S, int e)
{
    if (S->top - S->base >= S->stacksize)
    {
        S->base = (int*)realloc(S->base, (S->stacksize + STACKINCREMENT) * sizeof(int));
        if (!S->base)
            exit(OVERFLOW);
        S->top = S->base + S->stacksize;
        S->stacksize += STACKINCREMENT;
    }
    *S->top++ = e;
    return OK;
}
Status EnQueue(LinkQueue* Q, int e)
{
    QueuePtr p=NULL;
    p = (QueuePtr)malloc(sizeof(QNode));
    if (!p)
        exit(OVERFLOW);
    p->data = e;
    p->next = NULL;
    Q->rear->next = p;
    Q->rear = p;
    return OK;

}
Status StackEmpty(Sqstack S)
{
    if (S.top == S.base)
        return OK;
    else
        return ERROR;
}
Status QueueEmpty(LinkQueue Q)
{
    if (Q.front == Q.rear)
        return OK;
    else
        return ERROR;
}
Status Pop(Sqstack* S, int* e)
{
    if (S->top == S->base)
        return ERROR;
    *e = *(--S->top);
    return OK;
}
Status DeQueue(LinkQueue* Q, int *e)
{
    QueuePtr p=NULL;
    if (Q->front == Q->rear)
        return ERROR;
    p = Q->front->next;
    *e = p->data;
    Q->front->next = p->next;
    if (Q->rear == p)
        Q->rear = Q->front;
    free(p);
    return OK;
}
void AddEdge(ArcNode* p1, ArcNode* p2)
{
    ArcNode* p = p1;
    while (p->nextarc)
        p = p->nextarc;
    p->nextarc = p2;
}
void CreateGraph(ALGraph* G, int indegree[]) {
    printf("请输入当前图的顶点数和弧数:\n");
    scanf_s("%d %d", &G->vexnum, &G->arcnum);
    printf("请输入顶点:\n");
    for (int i = 0; i < G->vexnum; i++) {
        scanf_s(" %c", &G->vertices[i].data);
        G->vertices[i].firstarc = NULL;
    }

    for (int i = 0; i < G->arcnum; i++) {
        int start, end;
        while (1) {
            printf("请输入第%d条弧所依附的顶点及其所指向的顶点的位置信息:\n", i + 1);
            scanf_s("%d %d", &start, &end);
            if (start >= 0 && start < G->vexnum && end >= 0 && end < G->vexnum) {
                break;
            }
            else {
                printf("输入的顶点位置无效,请重新输入!\n");
            }
        }

        ArcNode* NewNode = (ArcNode*)malloc(sizeof(ArcNode));
        if (!NewNode) {
            printf("Memory allocation failed\n");
            exit(OVERFLOW);
        }
        NewNode->adjvex = end;
        NewNode->nextarc = NULL;
        indegree[end]++;
        if (G->vertices[start].firstarc == NULL) {
            G->vertices[start].firstarc = NewNode;
        }
        else {
            AddEdge(G->vertices[start].firstarc, NewNode);
        }
    }
}
Status LocateVex(MGraph G,VertexType v)
{
    int i;
    for (i = 0; i < G.vexnum; i++)
        if (v == G.vexs[i])
            return i;
    return -1;
}
Status CreateDG(MGraph* G, int indegree[]) {
    int i, j, x, y;
    VertexType v1, v2;
    printf("请输入顶点数和边数:\n");
    scanf_s("%d %d", &G->vexnum, &G->arcnum);
    for (i = 0; i < G->vexnum; i++)
        for (j = 0; j < G->vexnum; j++)
            G->arcs[i][j] = 0;
    printf("请输入顶点:\n");
    for (i = 0; i < G->vexnum; i++)
        scanf_s(" %c", &G->vexs[i]);

    for (i = 0; i < G->arcnum; i++) {
        while (1) {
            printf("请输入第%d条弧所依附的两个顶点:\n", i + 1);
            scanf_s(" %c", &v1);
            scanf_s(" %c", &v2);
            x = LocateVex(*G, v1);
            y = LocateVex(*G, v2);
            if (x != -1 && y != -1) {
                break;
            }
            else {
                printf("输入的顶点无效,请重新输入!\n");
            }
        }
        G->arcs[x][y] = 1;
        indegree[y]++;
    }
    return OK;
}
Status TopologicalSort(ALGraph *G,int indegree[])//邻接链表存储,栈实现拓扑排序
{
    Sqstack S;
    ArcNode* p;
    InitStack(&S);
    int i,k;
    for (i = 0; i < G->vexnum; i++)
        if (!indegree[i])
            Push(&S, i);
    int count = 0;
    while (!StackEmpty(S))
    {
        Pop(&S, &i);
        printf("%c", G->vertices[i].data);
        count++;
        for (p = G->vertices[i].firstarc; p; p = p->nextarc)
        {
            k = p->adjvex;
            if (!(--indegree[k]))
                Push(&S, k);
        }
    }
    if (count < G->vexnum)
    {
        printf("不符合拓扑排序条件,无法进行排序");
        return ERROR;
    }
       
    else
        return OK;
}
Status TopologicalSort2(ALGraph* G, int indegree[])
{
    LinkQueue Q;
    ArcNode* p;
    InitQueue(&Q);
    int i, k;
    for (i = 0; i < G->vexnum; i++)
        if (!indegree[i])
            EnQueue(&Q, i);
    int count = 0;
    while (!QueueEmpty(Q))
    {
        DeQueue(&Q, &i);
        printf("%c", G->vertices[i].data);
        count++;
        for (p = G->vertices[i].firstarc; p; p = p->nextarc)
        {
            k = p->adjvex;
            if (!(--indegree[k]))
                EnQueue(&Q, k);
        }
    }
    if (count < G->vexnum)
    {
        printf("不符合拓扑排序条件,无法进行排序");
        return ERROR;
    }

    else
        return OK;
}
Status TopologicalSort3(MGraph* G, int indegree[])
{
    Sqstack S;
    ArcNode* p;
    InitStack(&S);
    int i, k;
    for (i = 0; i < G->vexnum; i++)
        if (!indegree[i])
            Push(&S, i);
    int count = 0;
    while (!StackEmpty(S))
    {
        Pop(&S, &i);
        printf("%c", G->vexs[i]);
        count++;
        for (int k = 0; k < G->vexnum; k++)
        {
            if (G->arcs[i][k])
            {
                if (!(--indegree[k]))
                    Push(&S, k);
            }
        }
    }
    if (count < G->vexnum)
    {
        printf("不符合拓扑排序条件,无法进行排序");
        return ERROR;
    }

    else
        return OK;
}
Status TopologicalSort4(MGraph* G,int indegree[])//邻接矩阵存储,队列实现拓扑排序
{
    LinkQueue Q;
    InitQueue(&Q);
    int i, k;
    for (i = 0; i < G->vexnum; i++)
        if (!indegree[i])
            EnQueue(&Q, i);
    int count = 0;
    while (!QueueEmpty(Q))
    {
        DeQueue(&Q, &i);
        printf("%c", G->vexs[i]);
        count++;
        for (int k=0;kvexnum;k++)
        {
            if (G->arcs[i][k])
            {
                if (!(--indegree[k]))
                    EnQueue(&Q, k);
            }
        }
    }
    if (count < G->vexnum)
    {
        printf("不符合拓扑排序条件,无法进行排序");
        return ERROR;
    }

    else
        return OK;
}
int main() {
    int indegree[MAX_VERTEX_NUM] = { 0 };
    int fs, choice;
    do {
        printf("请选择有向图采用的存储结构:\n1.邻接链表  2.邻接矩阵  3.退出\n");
        scanf_s("%d", &fs);
        system("cls"); 

        if (fs == 3) {
            printf("程序已退出。\n");
            break; 
        }
        else if (fs == 1) {
            ALGraph* G = (ALGraph*)malloc(sizeof(ALGraph));
            CreateGraph(G, indegree);
            printf("请选择实现拓扑排序的方式:\n1.栈  2.队列\n");
            scanf_s("%d", &fs);
            system("cls");
            if (fs == 1) {
                TopologicalSort(G, indegree);
            }
            else if (fs == 2) {
                TopologicalSort2(G, indegree);
            }
            free(G); 
        }
        else if (fs == 2) {
            MGraph* G = (MGraph*)malloc(sizeof(MGraph));
            CreateDG(G, indegree);
            printf("请选择实现拓扑排序的方式:\n1.栈  2.队列\n");
            scanf_s("%d", &fs);
            system("cls");
            if (fs == 1) {
                TopologicalSort3(G, indegree);
            }
            else if (fs == 2) {
                TopologicalSort4(G, indegree);
            }
            free(G); 
        }
        else {
            printf("无效的输入,请重新选择。\n");
            continue;
        }
        printf("\n是否继续选择其他操作?(1.继续  2.退出)\n");
        scanf_s("%d", &choice);
        system("cls");

    } while (choice == 1); 

    return 0;
}

用c#写的可视化界面

//Form1.cs
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using YourProjectName.Models;

namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
        private List vertices;
        private List edges;
        private List sortedVertices;
        private Queue zeroIndegreeQueue;
        private Dictionary indegree;
        private const int ANIMATION_SPEED = 1000;
        private bool useStack = true; // 默认使用栈
        public Form1()
        {
            InitializeComponent();
            vertices = new List();
            edges = new List();
            sortedVertices = new List();
            zeroIndegreeQueue = new Queue();
            indegree = new Dictionary();
            SetupEventHandlers();
        }
        private void cmbAlgorithm_SelectedIndexChanged(object sender, EventArgs e)
        {
            useStack = cmbAlgorithm.SelectedItem.ToString().Contains("基于栈");
        }
        private void SetupEventHandlers()
        {
            btnCreate.Click += BtnCreate_Click;
            btnSort.Click += BtnSort_Click;
            btnNext.Click += BtnNext_Click;
            btnReset.Click += BtnReset_Click;
            drawPanel.Paint += DrawPanel_Paint;
        }

        private void BtnCreate_Click(object sender, EventArgs e)
        {
            try
            {
                if (cmbStorageType.SelectedItem.ToString() == "邻接矩阵")
                {
                    CreateGraphUsingMatrix();
                }
                else if(cmbStorageType.SelectedItem.ToString() == "邻接链表")
                {
                    CreateGraphUsingList();
                }
                else
                {
                    CreateGraphFromInput();
                    
                }
                LayoutGraph();
                drawPanel.Invalidate();
                btnSort.Enabled = true;
                btnNext.Enabled = false;
                UpdateStatus("图创建成功!");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void CreateGraphUsingMatrix()
        {
            int vertexCount = 6; 
            vertices.Clear();
            edges.Clear();
            sortedVertices.Clear();
            zeroIndegreeQueue.Clear();
            indegree.Clear();

            // 初始化顶点
            var vertexNames = new[] { 'A', 'B', 'C', 'D', 'E' ,'F'};
            for (int i = 0; i < vertexCount; i++)
            {
                var vertex = new Vertex(vertexNames[i]);
                vertices.Add(vertex);
                indegree[vertex] = 0;
            }

            // 邻接矩阵
            bool[,] adjacencyMatrix = new bool[vertexCount, vertexCount];

            // 添加边
            AddEdgeToMatrix(adjacencyMatrix, 'A', 'B');
            AddEdgeToMatrix(adjacencyMatrix, 'A', 'D');
            AddEdgeToMatrix(adjacencyMatrix, 'A', 'C');
            AddEdgeToMatrix(adjacencyMatrix, 'E', 'C');
            AddEdgeToMatrix(adjacencyMatrix, 'E', 'F');
            AddEdgeToMatrix(adjacencyMatrix, 'C', 'F');
            AddEdgeToMatrix(adjacencyMatrix, 'D', 'B');
            AddEdgeToMatrix(adjacencyMatrix, 'D', 'F');
            // 将邻接矩阵中的边转换为Edge对象
            for (int i = 0; i < vertexCount; i++)
            {
                for (int j = 0; j < vertexCount; j++)
                {
                    if (adjacencyMatrix[i, j])
                    {
                        edges.Add(new Edge(vertices[i], vertices[j]));
                    }
                }
            }
        }
        private void CreateGraphUsingList()
        {
            vertices.Clear();
            edges.Clear();
            sortedVertices.Clear();
            zeroIndegreeQueue.Clear();
            indegree.Clear();

            // 初始化顶点
            var vertexNames = new[] { 'A', 'B', 'C', 'D', 'E' };
            foreach (var v in vertexNames)
            {
                var vertex = new Vertex(v);
                vertices.Add(vertex);
                indegree[vertex] = 0;
            }

            // 使用邻接链表添加边
            AddEdgeToList('A', 'C');
            AddEdgeToList('B', 'C');
            AddEdgeToList('A', 'E');
            AddEdgeToList('D', 'E');
            AddEdgeToList('B', 'E');
            AddEdgeToList('B', 'D');
        }

        private void AddEdgeToList(char fromValue, char toValue)
        {
            var from = vertices.Find(v => v.Value == fromValue);
            var to = vertices.Find(v => v.Value == toValue);
            if (from == null || to == null)
            {
                throw new Exception($"边 {fromValue}->{toValue} 包含不存在的顶点!");
            }
            from.Neighbors.Add(to);
            edges.Add(new Edge(from, to)); // 创建并添加边
            indegree[to]++;
        }
        private void AddEdgeToMatrix(bool[,] matrix, char fromValue, char toValue)
        {
            int fromIndex = vertices.FindIndex(v => v.Value == fromValue);
            int toIndex = vertices.FindIndex(v => v.Value == toValue);
            if (fromIndex == -1 || toIndex == -1)
            {
                throw new Exception($"边 {fromValue}->{toValue} 包含不存在的顶点!");
            }
            matrix[fromIndex, toIndex] = true;
            indegree[vertices[toIndex]]++;
        }

        private void CreateGraphFromInput()
        {
            vertices.Clear();
            edges.Clear();
            sortedVertices.Clear();
            zeroIndegreeQueue.Clear();
            indegree.Clear();

            var vertexInput = txtVertices.Text.Replace(" ", "").Split(',');
            foreach (var v in vertexInput)
            {
                if (string.IsNullOrEmpty(v)) continue;
                var vertex = new Vertex(v[0]);
                vertices.Add(vertex);
                indegree.Add(vertex, 0); // Initialize indegree to 0
            }

            var edgeInput = txtEdges.Text.Replace(" ", "").Split(',');
            foreach (var e in edgeInput)
            {
                if (string.IsNullOrEmpty(e) || e.Length < 3) continue;
                if (e[1] != '-' || e[2] != '>')
                    throw new Exception("边的格式错误,请使用 A->B 格式!");
                var from = vertices.Find(v => v.Value == e[0]);
                var to = vertices.Find(v => v.Value == e[3]);
                if (from == null || to == null)
                    throw new Exception($"边 {e} 包含不存在的顶点!");
                edges.Add(new Edge(from, to));
                if (!indegree.ContainsKey(to))
                    indegree[to] = 0; 
                indegree[to]++;
                from.Neighbors.Add(to);
            }
        }

        private void LayoutGraph()
        {
            int radius = Math.Min(drawPanel.Width, drawPanel.Height) / 3;
            Point center = new Point(drawPanel.Width / 2 - 100, drawPanel.Height / 2);
            double startAngle = -Math.PI / 2;
            for (int i = 0; i < vertices.Count; i++)
            {
                double angle = startAngle + (2 * Math.PI * i / vertices.Count);
                int x = (int)(center.X + radius * Math.Cos(angle));
                int y = (int)(center.Y + radius * Math.Sin(angle));
                vertices[i].Location = new Point(x, y);
            }
        }
        private void DrawQueueInfo(Graphics g)
        {
            int y = drawPanel.Height - 100; // 距离底部100像素的位置
            int x = 10; // 距离左侧10像素的位置
            using (var font = new Font("微软雅黑", 15))
            using (var brush = new SolidBrush(Color.FromArgb(44, 62, 80)))
            {
                string queueInfo = useStack ? "栈中的元素: " : "队列中的元素: ";
                foreach (var vertex in zeroIndegreeQueue)
                {
                    queueInfo += vertex.Value + " ";
                }
                g.DrawString(queueInfo, font, brush, new Point(x, y));
            }
        }
        private void DrawPanel_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

            // 绘制边
            foreach (var edge in edges)
            {
                if (edge.Visible)
                {
                    using (var pen = new Pen(edge.Color, 2))
                    {
                        DrawArrow(e.Graphics, edge.From.Location, edge.To.Location, pen);
                    }
                }
            }

            // 绘制顶点
            foreach (var vertex in vertices)
            {
                var rect = new Rectangle(
                    vertex.Location.X - 20,
                    vertex.Location.Y - 20,
                    40, 40);

                using (var brush = new SolidBrush(vertex.Color))
                {
                    e.Graphics.FillEllipse(brush, rect);
                }

                using (var brush = new SolidBrush(Color.White))
                {
                    var format = new StringFormat
                    {
                        Alignment = StringAlignment.Center,
                        LineAlignment = StringAlignment.Center
                    };
                    e.Graphics.DrawString(
                        vertex.Value.ToString(),
                        new Font("Arial", 12, FontStyle.Bold),
                        brush,
                        vertex.Location,
                        format);
                }
            }

            // 绘制已排序的顶点
            foreach (var sortedVertex in sortedVertices)
            {
                var rect = new Rectangle(
                    sortedVertex.Location.X - 20,
                    sortedVertex.Location.Y - 20,
                    40, 40);

                using (var brush = new SolidBrush(sortedVertex.Color))
                {
                    e.Graphics.FillEllipse(brush, rect);
                }

                using (var brush = new SolidBrush(Color.White))
                {
                    var format = new StringFormat
                    {
                        Alignment = StringAlignment.Center,
                        LineAlignment = StringAlignment.Center
                    };
                    e.Graphics.DrawString(
                        sortedVertex.Value.ToString(),
                        new Font("Arial", 12, FontStyle.Bold),
                        brush,
                        sortedVertex.Location,
                        format);
                }
            }

            DrawQueueInfo(e.Graphics);
            DrawInDegreeInfo(e.Graphics);
        }
        private void DrawArrow(Graphics g, Point start, Point end, Pen pen)
        {
            const float arrowSize = 15;
            float angle = (float)Math.Atan2(end.Y - start.Y, end.X - start.X);

            Point adjustedStart = new Point(
                (int)(start.X + 22 * Math.Cos(angle)),
                (int)(start.Y + 22 * Math.Sin(angle))
            );

            Point adjustedEnd = new Point(
                (int)(end.X - 22 * Math.Cos(angle)),
                (int)(end.Y - 22 * Math.Sin(angle))
            );

            g.DrawLine(pen, adjustedStart, adjustedEnd);

            Point[] arrowHead = new Point[]
            {
                adjustedEnd,
                new Point(
                    (int)(adjustedEnd.X - arrowSize * Math.Cos(angle - Math.PI / 6)),
                    (int)(adjustedEnd.Y - arrowSize * Math.Sin(angle - Math.PI / 6))
                ),
                new Point(
                    (int)(adjustedEnd.X - arrowSize * Math.Cos(angle + Math.PI / 6)),
                    (int)(adjustedEnd.Y - arrowSize * Math.Sin(angle + Math.PI / 6))
                )
            };

            g.FillPolygon(new SolidBrush(pen.Color), arrowHead);
        }

        private void DrawInDegreeInfo(Graphics g)
        {
            int y = 20;
            int x = drawPanel.Width - 300; 
            using (var font = new Font("微软雅黑", 14))
            using (var brush = new SolidBrush(Color.FromArgb(44, 62, 80)))
            {
                foreach (var vertex in vertices) 
                {
                    string info = $"顶点 {vertex.Value} 的入度: {indegree[vertex]}";
                    g.DrawString(info, font, brush, new Point(x, y));
                    y += 40;
                }
            }
        }

        private void BtnSort_Click(object sender, EventArgs e)
        {
            btnSort.Enabled = false;
            btnNext.Enabled = true;
            sortedVertices.Clear();
            var zeroIndegreeVertices = vertices.Where(v => indegree[v] == 0).ToList();

            if (useStack)
            { 
                var stack = new Stack(zeroIndegreeVertices.OrderByDescending(v => v.Value));
                zeroIndegreeQueue = new Queue(stack); 
            }
            else
            {
                zeroIndegreeQueue = new Queue(zeroIndegreeVertices.OrderBy(v => v.Value));
            }

            foreach (var vertex in zeroIndegreeQueue)
            {
                vertex.Color = Color.Blue;
            }

            lblStatus.Text = "";
            drawPanel.Invalidate();
        }

        private async void BtnNext_Click(object sender, EventArgs e)
        {
            if (zeroIndegreeQueue.Count == 0)
            {
                if (sortedVertices.Count < vertices.Count)
                {
                    UpdateStatus("无法继续排序,图中存在环或未处理的顶点。");
                }
                else
                {
                    UpdateStatus("拓扑排序完成!");
                }
                btnNext.Enabled = false;
                return;
            }

            Vertex current;
            if (useStack)
            {
                var stack = new Stack(zeroIndegreeQueue);
                current = stack.Pop();
                zeroIndegreeQueue = new Queue(stack);
            }
            else
            {
                current = zeroIndegreeQueue.Dequeue();
            } 
            await AnimateVertexColor(current, Color.Green); 
            sortedVertices.Add(current);
           

            foreach (var edge in edges)
            {
                if (edge.From == current && edge.Visible)
                {
                    edge.Visible = false;
                    if (--indegree[edge.To] == 0)
                    {
                        if (useStack)
                        {
                            var stack = new Stack(zeroIndegreeQueue);
                            stack.Push(edge.To);
                            zeroIndegreeQueue = new Queue(stack);
                        }
                        else
                        {
                            zeroIndegreeQueue.Enqueue(edge.To);
                        }
                        edge.To.Color = Color.Blue; 
                    }
                }
            }
            UpdateSortingResult();
            LayoutSortedVertices(); 
            drawPanel.Invalidate(); // 触发重绘
        }
        private void LayoutSortedVertices()
        {
            // 定义最左边的X坐标
            int x = 20;
            // 每个顶点的直径
            int diameter = 40;
            // 顶点之间的垂直间距
            int gap = 20;

            for (int i = 0; i < sortedVertices.Count; i++)
            {
                // 计算Y坐标,每个顶点之间有一定的间隔
                int y = 20 + i * (diameter + gap);
                // 设置顶点的新位置
                sortedVertices[i].Location = new Point(x, y);
            }
        }
        private async Task AnimateVertexColor(Vertex vertex, Color color)
        {
            vertex.Color = color;
            drawPanel.Invalidate(); 
            await Task.Delay(ANIMATION_SPEED);
        }

        private async Task AnimateEdgeRemoval(Vertex from, Vertex to)
        {
            var edge = edges.Find(e => e.From == from && e.To == to);
            if (edge != null)
            {
                edge.Visible = false;
                drawPanel.Invalidate();
                await Task.Delay(ANIMATION_SPEED / 2);
            }
        }

        private void UpdateStatus(string message)
        {
            lblStatus.Text = message;
            lblStatus.ForeColor = message.Contains("错误") ?
                Color.FromArgb(192, 57, 43) : Color.FromArgb(39, 174, 96);
        }

        private void UpdateSortingResult()
        {
            string result = "拓扑排序结果:";
            for (int i = 0; i < sortedVertices.Count; i++)
            {
                result += sortedVertices[i].Value;
                if (i < sortedVertices.Count - 1)
                {
                    result += " -> ";
                }
            }
            lblStatus.Text = result;
            lblStatus.ForeColor = Color.FromArgb(39, 174, 96);
        }

        private void BtnReset_Click(object sender, EventArgs e)
        {
            vertices.Clear();
            edges.Clear();
            sortedVertices.Clear();
            zeroIndegreeQueue.Clear();
            indegree.Clear();
            txtVertices.Clear();
            txtEdges.Clear();
            btnSort.Enabled = false;
            btnNext.Enabled = false;
            UpdateStatus("");
            drawPanel.Invalidate();
        }
    }
}
//Form1.Designer.cs
namespace WinFormsApp1
{
    partial class Form1
    {
        private System.ComponentModel.IContainer components = null;
        private Panel drawPanel;
        private TextBox txtVertices;
        private TextBox txtEdges;
        private Button btnCreate;
        private Button btnSort;
        private Button btnNext;
        private Button btnReset;
        private ComboBox cmbAlgorithm;
        private ComboBox cmbStorageType;
        private Label lblStatus;

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.Size = new System.Drawing.Size(2600, 1800); // 调整窗口大小
            this.Text = "拓扑排序可视化";
            this.BackColor = Color.FromArgb(236, 240, 241);
            this.StartPosition = FormStartPosition.CenterScreen;

            // 绘图面板
            drawPanel = new Panel
            {
                Location = new Point(80, 200),
                Size = new Size(2400, 1200),
                BackColor = Color.White,
                BorderStyle = BorderStyle.FixedSingle
            };

            // 顶点输入框
            txtVertices = new TextBox
            {
                Location = new Point(480, 40),
                Size = new Size(550, 60),
                Font = new Font("微软雅黑", 10F),
                PlaceholderText = "输入顶点 (例如: A,B,C)"
            };

            // 边输入框
            txtEdges = new TextBox
            {
                Location = new Point(480, 120),
                Size = new Size(550, 60),
                Font = new Font("微软雅黑", 10F),
                PlaceholderText = "输入边 (例如: A->B,B->C)"
            };

            // 算法选择下拉框
            cmbAlgorithm = new ComboBox
            {
                Location = new Point(80, 120),
                Size = new Size(350, 60),
                DropDownStyle = ComboBoxStyle.DropDownList,
                Font = new Font("微软雅黑", 10F)
            };
            cmbAlgorithm.Items.AddRange(new object[] {
        "基于栈的拓扑排序",
        "基于队列的拓扑排序"
    });
            cmbAlgorithm.SelectedIndex = 0;

            // 存储方式选择下拉框 
            cmbStorageType = new ComboBox
            {
                Location = new Point(80, 40),
                Size = new Size(350, 60),
                DropDownStyle = ComboBoxStyle.DropDownList,
                Font = new Font("微软雅黑", 10F)
            };
            cmbStorageType.Items.AddRange(new object[] {
        "邻接矩阵",
        "邻接链表",
        "手动输入"
    });
            cmbStorageType.SelectedIndex = 0;

            // 按钮
            btnCreate = CreateStyledButton("创建图", new Point(1200, 40));
            btnSort = CreateStyledButton("开始排序", new Point(1550, 40));
            btnNext = CreateStyledButton("下一步", new Point(1900, 40));
            btnReset = CreateStyledButton("重置", new Point(2250, 40));
            btnSort.Enabled = false;
            btnNext.Enabled = false;

            // 状态标签
            lblStatus = new Label
            {
                Location = new Point(80, 1440),
                Size = new System.Drawing.Size(2200, 60),
                Font = new Font("微软雅黑", 14F, FontStyle.Bold),
                ForeColor = Color.FromArgb(52, 73, 94)
            };

            // 添加控件
            Controls.AddRange(new Control[] {
        drawPanel, txtVertices, txtEdges, cmbAlgorithm, cmbStorageType,
        btnCreate, btnSort, btnNext, btnReset, lblStatus
    });
            cmbAlgorithm.SelectedIndexChanged += cmbAlgorithm_SelectedIndexChanged;
        }
        private Button CreateStyledButton(string text, Point location)
        {
            var btn = new Button
            {
                Text = text,
                Location = location,
                Size = new Size(200, 80),
                Font = new Font("微软雅黑", 10F),
                FlatStyle = FlatStyle.Flat,
                BackColor = Color.FromArgb(52, 152, 219), // 初始颜色
                ForeColor = Color.White,
                Cursor = Cursors.Hand
            };

            // 设置鼠标悬浮时的事件处理
            btn.MouseEnter += (sender, e) =>
            {
                // 鼠标悬浮时改变背景颜色为绿色
                ((Button)sender).BackColor = Color.Green;
            };

            // 设置鼠标离开时的事件处理
            btn.MouseLeave += (sender, e) =>
            {
                // 鼠标离开时恢复初始背景颜色
                ((Button)sender).BackColor = Color.FromArgb(52, 152, 219);
            };

            btn.FlatAppearance.BorderSize = 0; // 如果您不想要边框,可以设置边框大小为0
            return btn;
        }
    }
}
//Edge.cs
using System.Drawing;

namespace YourProjectName.Models
{
    public class Edge
    {
        public Vertex From { get; set; }
        public Vertex To { get; set; }
        public bool Visible { get; set; }
        public Color Color { get; set; }

        public Edge(Vertex from, Vertex to)
        {
            From = from;
            To = to;
            Visible = true;
            Color = Color.FromArgb(44, 62, 80);
        }
    }
}
//Vertex.cs
using System.Drawing;

namespace YourProjectName.Models
{
    public class Vertex
    {
        public char Value { get; set; }
        public Point Location { get; set; }
        public List Neighbors { get; set; }
        public int InDegree { get; set; }
        public Color Color { get; set; }

        public Vertex(char value)
        {
            Value = value;
            Neighbors = new List();
            InDegree = 0;
            Color = Color.Black; // 初始颜色
        }
    }
}
//Program.cs
using System;
using System.Windows.Forms;

namespace WinFormsApp1
{
    internal static class Program
    {
        /// 
        ///  The main entry point for the application.
        /// 
        [STAThread]
        static void Main()
        {
            ApplicationConfiguration.Initialize();
            Application.Run(new Form1());
        }
    }
}

你可能感兴趣的:(数据结构,算法)