上面是题目:实际上的结果应该是
A E D C B G F
…我又算错了,这次的错误显示在,他已经遍历到了
A A E D C D
首先是我自己之前制作的 顺序表 seqList 接口就不写了直接 放功能
private T[] datas;
private int ListLength;
private int ListSize;
//private int index;//序号 虽然不知道有没有用
public seqList(int size)
{
ListSize = size;
datas = new T[ListSize];
ListLength = 0;
}
public seqList()
{
}
public void getMinEdge()
{
throw new NotImplementedException();
}
public void ClearList()
{
ListLength = 0;
}
public int GetLenth()
{
return ListLength;
}
public bool IsEmpty()
{
return ListLength == 0;
}
public void ListInsert(T item, int index)
{
if (!IsFull())
{
for (int i = ListSize - 2; i >= index; i--)/
{
datas[i + 1] = datas[i];//这个循环被跳过了
}
datas[index] = item;
ListLength++;
}
}
public void Pop(T item)
{
if (ListLength < ListSize)
{
datas[ListLength] = item;
ListLength++;
}
}
public T Peek(int index)
{
return datas[index];
}
然后是边 Edge的类
class Edge
{
//边的属性需要哪些参数,首先是需要A点,其次是需要B点
//还需要这些边的权值,最后是bool值
public int NodeIndexA;
public int NodeIndexB;
public int edgeValue;
public bool isSelected;
public Edge(int indexA,int indexB,int value)
{
NodeIndexA = indexA;
NodeIndexB = indexB;
edgeValue = value;
isSelected = false;
}
接下来就是prim算法的类,这个类是我之前自己制作图的类,
不过我把默认所有无向图最开始的值设置为了50(比其余所有的值都要大)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 图csharp
{
class myPic : iPic
{
private int Capacity;
private int NodeCount;
Queue<int> GDdata = new Queue<int>();//把看见的边都存起来;
public int seqNodeCount;
private int[] array;//邻接矩阵
private picNode[] NodeArray;
//普里姆树所需要的 顺序表
public seqList<picNode> seqNodeLists;//备用点
public seqList<Edge> seqEdgeLists;//备用边储存
public seqList<picNode> MinNodeList;//最小的点
public seqList<Edge> SelectMindEdgeLists;//最终找到的边
//primTree所需要的参数
//我们还需要一个存放所有结点的数组 SeqNodeLists
//我们还需要一个存放全部不需要的边的数组,seqEdgeLists
//需要一个存放最终最小边的数组 SelectMinEdgeLists
//需要一个存放最终结点以及顺序数组 MinNodeList;
//普里姆生成树
public void primTree(int nodeIndex)
{ //一直到最后被选择的边Edge 已经有 (点-1)条,结束循环
if (SelectMindEdgeLists.GetLenth() != Capacity - 1)
{ // 遍历7次,包括自己,因为所有值的初始值我设置为了50(比所有权值大)
for (int i = 0; i < seqNodeLists.GetLenth(); i++)
{
int MinValue = getValueFromArray(nodeIndex, i);
int MinIndex = i;
//没有去除重复的,无向边,导致错误
Edge edge = new Edge(nodeIndex, i, MinValue);
seqEdgeLists.Pop(edge);//把当前nodeIndex所有的边存储起来
}
int minEdge = seqEdgeLists.Peek(0).edgeValue;//取出第一条边的权值
int minEdgeIndex = default(int); //以及最小权值边所在的结点A
int minEdgeIndexB = default(int); //以及最小权值边的结点B
int DeletePoint = default(int); //记录这条最小权值边所在seq中的位置。
for (int i = 1; i < seqEdgeLists.GetLenth() - 1; i++) //第一条已取走
{
for (int j = 0; j < MinNodeList.GetLenth(); j++)
{//比较最小权值之前,必须确认这个最小权值边
//左右两个结点不能都在最终所选结点里
//第一次遍历时,最终所选结点中没有元素,第二次将有第一次的nodeIndex
if (seqEdgeLists.Peek(i).NodeIndexA == MinNodeList.Peek(j).Data &&
seqEdgeLists.Peek(i).NodeIndexB == MinNodeList.Peek(j).Data)
{continue;}
else
{ //如果有权重值更小的,替换掉
if (minEdge >= seqEdgeLists.Peek(i).edgeValue)
{
minEdge = seqEdgeLists.Peek(i).edgeValue;//记录值
DeletePoint = i; //记录所在点,方便删除
minEdgeIndex=seqEdgeLists.Peek(i).NodeIndexA;
minEdgeIndexB=seqEdgeLists.Peek(i).NodeIndexB;
//第一种情况,一个点是nodeIndex,第二个点是新点
//第二种情况,因为无向边重复了两次,反过来被选择了
//第三种情况,只有一个是已有的点,但不是本次循环的起点
}
else { continue; }
}
else { continue; }
}}
}
//那么在这个循环结束之后,我得到的是最小的权值 以及他相应的结点
Edge SelectMinEdge = new Edge(minEdgeIndex, minEdgeIndexB, minEdge);
//把这个最小边找到,放入最小边的集合。
SelectMindEdgeLists.Pop(SelectMinEdge); //放进去
seqEdgeLists.ListDelete(DeletePoint); //在池子中把他删掉
//无论如何,必须要有一个点是当前有的,另外一个是当前没有的
//寻找新的结点开始遍历
int NewnodeIndex = minEdgeIndex;
//把本次循环的结点放入最小结点的集合里面
MinNodeList.Pop(seqNodeLists.Peek(nodeIndex));
primTree(NewnodeIndex);
}
}
public void SetSeqList()
{
seqNodeLists = new seqList<picNode>(Capacity);
seqEdgeLists = new seqList<Edge>(Capacity * Capacity);
MinNodeList = new seqList<picNode>(Capacity);
SelectMindEdgeLists = new seqList<Edge>(Capacity - 1);
}
private int getValueFromArray(int row, int col)
{
if (row < 0 || row >= Capacity)
{ return default(int); }
if (col < 0 || col >= Capacity)
{ return default(int); }
int temp = array[row * Capacity + col];
return temp;
}
public myPic(int capacity)
{
NodeCount = 0;
Capacity = capacity;
seqNodeCount = 0;
// NodeArray = new picNode[capacity];//设置结点的数组
seqList<picNode> seqNodeLists = new seqList<picNode>(capacity);//换成自己的数组
array = new int[capacity * capacity];//设置数据的数组
for (int i = 0; i < array.Length; i++)
{
array[i] = 50;
}
}
public void AddNode(picNode node)
{ //结点矩阵中的 结点数据等于 输入数据
//NodeArray[NodeCount] = node;
//NodeCount++;
seqNodeLists.ListInsert(node, seqEdgeLists.GetLenth());
}
public void DeleteNode(int nodeIndex)
{
for (int i = 0; i < NodeCount - nodeIndex - 1; i++)
{
NodeArray[nodeIndex] = NodeArray[nodeIndex + 1];//后面一个位置的数字会变成前面一个
}//在最后数组被减干净之后
NodeCount--;
}
public void breadthFirstTraverse(int nodeIndex)//但是得先设置个数组int 存放广度数据
{//广度优先遍历//先从根结点访问干净 然后访问下一个结点
int value = 0;
Console.Write(seqNodeLists.Peek(nodeIndex).Data + " ");
seqNodeLists.Peek(nodeIndex).ChangeVisited(true);
for (int i = 0; i < Capacity; i++)
{
value = getValueFromArray(nodeIndex, i);//取得值
if (value == 1)//找到b了 // 输出b //找下一个 // 弄个队列 先进的先出
{
if (seqNodeLists.Peek(nodeIndex).isVisited == false)
{
GDdata.Enqueue(i);//把找到的数据放进 队列 我在外面自己set的队列
}
else
{
continue;
}
}
else//当value = 0的时候
{
continue;
}
}
//遍历之后
if (GDdata.Count > 0)
{
breadthFirstTraverse(GDdata.Dequeue());
}
}
public void depthFirstTraverse(int nodeIndex)
{//深度遍历 先访问根 // 首先这个nodeIndex 是什么意思 是从哪里开始吗
int value; ;
//这里是会进行 NodeArray【length】次的遍历
Console.Write(seqNodeLists.Peek(nodeIndex).Data + " ");
seqNodeLists.Peek(nodeIndex).ChangeVisited(true);
for (int i = 0; i < Capacity; i++)
{ //我彻底 明白了 所以当 我的序列为0 时 自动搜索第0行的全部元素
value = getValueFromArray(nodeIndex, i);
if (value == 1)//证明搜到1,是无向图,可以继续下去
{
if (seqNodeLists.Peek(nodeIndex).isVisited == true)
{ continue; }
else
{ depthFirstTraverse(i); }
}
else
{
continue;
}
}
}
public void printMatrix()
{
for (int i = 0; i < Capacity; i++)
{
for (int k = 0; k < Capacity; k++)
{
Console.Write(array[i * Capacity + k]);
Console.Write(" ");
}
Console.WriteLine();
}
}
public void resetNode()
{
for (int i = 0; i < seqNodeLists.GetLenth(); i++)
{
// NodeArray[i].ChangeVisited(false);
seqNodeLists.Peek(i).ChangeVisited(false);
}
}
public bool SetValueToMatrixForDirectedGraph(int row, int col, int val)
{//把数值 关系 复制到 有向图中 // row 行 col 列
if (row < 0 || row >= Capacity)
{ return false; }
if (col < 0 || col >= Capacity)
{ return false; }
array[row * Capacity + col] = val;
return true;
}
public bool SetValueToMatrixForUndiretedGraph(int row, int col, int val)
{
if (row < 0 || row >= Capacity)
{ return false; }
if (col < 0 || col >= Capacity)
{ return false; }
array[row * Capacity + col] = val;
array[col * Capacity + row] = val;
return true;
}
public void setGDdate()
{
Queue<int> GDdata = new Queue<int>(Capacity);
}
}
}
最后是我运行的程序。
namespace 图csharp
{
class Program
{
static void Main(string[] args)
{
myPic myPic = new myPic(7);
myPic.SetSeqList();
//先做结点
picNode nodeA = new picNode('A');
picNode nodeB = new picNode('B');
picNode nodeC = new picNode('C');
picNode nodeD = new picNode('D');
picNode nodeE = new picNode('E');
picNode nodeF = new picNode('F');
picNode nodeG = new picNode('G');
myPic.seqNodeLists.Pop(nodeA);
myPic.seqNodeLists.Pop(nodeB);
myPic.seqNodeLists.Pop(nodeC);
myPic.seqNodeLists.Pop(nodeD);
myPic.seqNodeLists.Pop(nodeE);
myPic.seqNodeLists.Pop(nodeF);
myPic.seqNodeLists.Pop(nodeG);
myPic.SetValueToMatrixForUndiretedGraph(0, 1,19);//A连B
myPic.SetValueToMatrixForUndiretedGraph(0, 4,14);
myPic.SetValueToMatrixForUndiretedGraph(0, 6,18);
myPic.SetValueToMatrixForUndiretedGraph(1, 2, 5);
myPic.SetValueToMatrixForUndiretedGraph(1, 3, 7);
myPic.SetValueToMatrixForUndiretedGraph(1, 4,12);
myPic.SetValueToMatrixForUndiretedGraph(2, 3, 3);
myPic.SetValueToMatrixForUndiretedGraph(3, 4, 8);
myPic.SetValueToMatrixForUndiretedGraph(3, 5,21);
myPic.SetValueToMatrixForUndiretedGraph(4, 6,16);
myPic.SetValueToMatrixForUndiretedGraph(5, 6,27);
myPic.printMatrix();
myPic.primTree(0);
for (int i = 0; i < myPic.MinNodeList.GetLenth(); i++)
{
Console.WriteLine(myPic.MinNodeList.Peek(i).Data);
}
for (int i = 0; i < myPic.SelectMindEdgeLists.GetLenth(); i++)
{
Console.WriteLine(myPic.SelectMindEdgeLists.Peek(i).edgeValue);
}
Console.ReadKey();
}
}
}