當前位置:首頁 » 服務存儲 » 樹可以用鄰接矩陣存儲
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

樹可以用鄰接矩陣存儲

發布時間: 2022-08-11 22:23:04

Ⅰ matlab中如何存儲樹希望提供代碼,萬分感謝,本人編程涉及到剪枝

MATLAB里沒有指針。但是考慮到樹只是圖的一種特例,LZ可以考慮用圖的存儲策略,用鄰接矩陣保存樹是不需要指針的,而且MATLAB對矩陣運算比較效率。就是浪費點空間而已。

Ⅱ 怎樣將一棵二叉樹的存儲結構轉化為一個無向圖的存儲結構,誰能說說編程思想啊

圖的存儲機構一般用鄰接矩陣或鄰接表,二叉樹一般是鏈表結構,就是把鏈表變成臨近矩陣了,用中序形勢對鏈表節點進行編號和訪問並做為臨近矩陣的順序,用中序訪問,對當前節點和後繼節點判斷,然後置對應的矩陣為1,(a[當前],[後繼]=1 ,a[後繼],[當前]=1 ) ,中序訪問完就可以了

Ⅲ 數據結構 ~~~~~最小生成樹問題

/* 用鄰接矩陣表示的圖的prim演算法的源程序*/

#include<stdio.h>
#define MAXVEX 6

typedef char VexType;

typedef float AdjType;

typedef struct {

int n;

/* 圖的頂點個數 */

/*VexType vexs[MAXVEX];

頂點信息 */

AdjType arcs[MAXVEX][MAXVEX];
/* 邊信息 */
} GraphMatrix;

typedef struct{

int start_vex, stop_vex;

/* 邊的起點和終點 */

AdjType weight;

/* 邊的權 */
} Edge;

Edge mst[5];

#define MAX 1e+8

void prim(GraphMatrix * pgraph, Edge mst[]) {

int i, j, min, vx, vy;

float weight, minweight; Edge edge;

for (i = 0; i < pgraph->n-1; i++) {

mst[i].start_vex = 0;

mst[i].stop_vex = i+1;

mst[i].weight = pgraph->arcs[0][i+1];

}

for (i = 0; i < pgraph->n-1; i++) {

/* 共n-1條邊 */

minweight = MAX; min = i;

for (j = i; j < pgraph->n-1; j++)/* 從所有邊(vx,vy)(vx∈U,vy∈V-U)中選出最短的邊 */

if(mst[j].weight < minweight) {

minweight = mst[j].weight;

min = j;

}

/* mst[min]是最短的邊(vx,vy)(vx∈U, vy∈V-U),將mst[min]加入最小生成樹 */

edge = mst[min];

mst[min] = mst[i];

mst[i] = edge;

vx = mst[i].stop_vex;

/* vx為剛加入最小生成樹的頂點的下標 */

for(j = i+1; j < pgraph->n-1; j++) { /* 調整mst[i+1]到mst[n-1] */

vy=mst[j].stop_vex; weight = pgraph->arcs[vx][vy];

if (weight < mst[j].weight) {

mst[j].weight = weight;

mst[j].start_vex = vx;

}

}

}
}
GraphMatrix graph = {

6,

{{0,10,MAX,MAX,19,21},

{10,0,5,6,MAX,11},

{MAX,5,0,6,MAX,MAX},

{MAX,6,6,0,18,14},

{19,MAX,MAX,18,0,33},

{21,11,MAX,14,33,0}

}
};

int main(){

int i;

prim(&graph,mst);

for (i = 0; i < graph.n-1; i++)

printf("(%d %d %.0f)\
", mst[i].start_vex,

mst[i].stop_vex, mst[i].weight);

return 0;
}

Ⅳ 編程實現以鄰接表或鄰接矩陣為存儲結構,圖的廣度和深度優先搜索

/*******************************************
圖的遍歷演示
以鄰接多重表為存儲結構,實現連通無向圖的深度優先和廣度優先遍歷.
以用戶指定的結點為起點,分別輸出每種遍歷下的結點訪問序列和相應生成樹的邊集.
*******************************************/
#include<iostream>
# include <string.h>
# include <malloc.h>
# include <conio.h>

using namespace std;

int visited[30];
# define MAX_VERTEX_NUM 30
# define OK 1
//typedef int VertexType;
typedef int InfoType;

typedef struct ArcNode //弧
{
int adjvex;
struct ArcNode *nextarc;
}ArcNode;

typedef struct VNode//表頭
{
int data;
ArcNode *firstarc;
}VNode,AdjList[MAX_VERTEX_NUM];

typedef struct//圖
{
AdjList vertices;
int vexnum,arcnum;
int kind;
}ALGraph;

void CreateDG(ALGraph &G)
{
int k,i,v1;
cout<<endl<<"請輸入結點個數: ";
cin>>G.vexnum;

cout<<"請輸入弧的個數: ";
cin>>G.arcnum;

for(i=1;i<=G.vexnum;i++)//初使化表頭
{
G.vertices[i].data=i;
G.vertices[i].firstarc=NULL;
}

for(k=1;k<=G.vexnum;k++) //輸入邊
{

int v2;
cout<<"請輸入與結點"<<k<<"相鄰的邊數:";
cin>>v2;
cout<<"請輸入與第"<<k<<"個結點相連的結點編號: ";
cin>>v1;
ArcNode *p;
p=(ArcNode*)malloc(sizeof(ArcNode));
if(!p) exit(-1);
p->adjvex=v1;
p->nextarc=NULL;
G.vertices[k].firstarc=p;

for(int i=1;i<v2;i++)
{
int m;
cout<<"請輸入與第"<<k<<"個結點相連的結點編號: ";
cin>>m;

ArcNode *q;
q=(ArcNode *)malloc(sizeof(ArcNode));//動態指針
if(!q) exit(-1);

q->adjvex=m; //頂點給P
q->nextarc=NULL;
p->nextarc=q;
p=q;
//free(q);
}
//free(p);
}
}

void DFS (ALGraph G,int v )//深度搜索
{

visited[v]=1;
cout<<G.vertices[v].data<<" ";
ArcNode *x;
x=(ArcNode*)malloc(sizeof(ArcNode));
if(!x) exit(-1);
x=G.vertices[v].firstarc;
int w;
for (;x;x=x->nextarc)
{ w=x->adjvex;
if(visited[w]==0)
DFS(G,w);
}
}

void DFSB (ALGraph G,int v)//深度搜索的邊集
{

visited[v]=1;
ArcNode *y;
y=(ArcNode*)malloc(sizeof(ArcNode));
if(!y) exit(-1);
y=G.vertices[v].firstarc;
int u=G.vertices[v].data;
int w;
for(;y;y=y->nextarc)
{ w=y->adjvex;
if(visited[w]==0)
{
cout<<u<<"--->"<<w<<endl;
DFSB(G,w);
}
}
}

typedef struct QNode
{
int data;
QNode *next;
}QNode,*QueuePtr;

typedef struct
{
QueuePtr front;
QueuePtr rear;
}LinkQueue;

void InitQueue (LinkQueue &Q)//建立一個空隊列
{
Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
if(!Q.front) exit(-1);
Q.front->next=NULL;
}

void EnQueue (LinkQueue &Q,int e)//進隊
{
QNode *p;
p=(QNode*)malloc(sizeof(QNode));
if(!p) exit(-1);
p->data=e;
p->next=NULL;
Q.rear->next=p;
Q.rear=p;
//free(p);
}
int DeQueue (LinkQueue &Q,int &e)//出隊
{
if(Q.front==Q.rear)
return -1;
QNode *p;
p=(QNode*)malloc(sizeof(QNode));
if(!p) exit(-1);
p=Q.front->next;
e=p->data;
Q.front->next=p->next;
if(Q.rear==p)
Q.rear=Q.front;
free(p);
return e;
}

int QueueEmpty (LinkQueue Q)//判斷隊列是否為空
{
if(Q.front==Q.rear)
return 1;
return 0;
}

void BFS(ALGraph G,int v)//廣度搜索
{

int u;
LinkQueue Q;
InitQueue(Q);
if(visited[v]==0)
{
visited[v]=1;
cout<<G.vertices[v].data<<" ";
EnQueue(Q,v);
while(QueueEmpty(Q)!=1)
{
DeQueue(Q,u);
ArcNode *z;
z=(ArcNode*)malloc(sizeof(ArcNode));
if(!z) exit(-1);
z=G.vertices[u].firstarc;
/*
for(int w=z->adjvex;w>=0;w=z->nextarc->adjvex)
{
if(visited[w]==0)
{
visited[w]=1;
cout<<w<<" ";
EnQueue(Q,w);
}
}*/
int w;
for(;z;z=z->nextarc)
{ w=z->adjvex;
if(visited[w]==0)
{
visited[w]=1;
cout<<w<<" ";
EnQueue(Q,w);
}
}
}
}
}

void BFSB (ALGraph G,int v)//廣度搜索的邊集
{

int u;
LinkQueue Q;
InitQueue(Q);
if(visited[v]==0)
{
visited[v]=1;
EnQueue(Q,v);
while(QueueEmpty(Q)!=1)
{
DeQueue(Q,u);
ArcNode *r;
r=(ArcNode*)malloc(sizeof(ArcNode));
if(!r) exit(-1);
r=G.vertices[u].firstarc;
int w;
for(;r!=NULL;r=r->nextarc)
{ w=r->adjvex;
if(visited[w]==0)
{
visited[w]=1;
cout<<u<<"--->"<<w<<endl;
EnQueue(Q,w);
}
}
}
}
}

int main()
{
int i;
ALGraph G;
CreateDG(G);
int x;
cout<<"請輸入結點數:";
cin>>x;
cout<<"鄰接表為:"<<endl;
for(int j=1;j<=x;j++)
{
cout<<G.vertices[j].data<<" ";
ArcNode *p;
p=(ArcNode*)malloc(sizeof(ArcNode));
if(!p) exit(-1);
p=G.vertices[j].firstarc;
while(p)
{
cout<<p->adjvex<<" ";
p=p->nextarc;
}
cout<<endl;
}

cout<<"請輸入第一個要訪問的結點序號:"<<endl;
int n;
cin>>n;

for( i=0;i<30;i++)
visited[i]=0;
cout<<"廣度搜索:"<<endl;
BFS(G,n);

for( i=0;i<30;i++)
visited[i]=0;
cout<<endl;
cout<<"邊集:"<<endl;
BFSB(G,n);

for( i=0;i<30;i++)
visited[i]=0;
cout<<"深度搜索:"<<endl;
DFS(G,n);

for( i=0;i<30;i++)
visited[i]=0;
cout<<endl;
cout<<"邊集:"<<endl;
DFSB(G,n);

//system("pause");
return 0;
}

前幾天上機剛好做了這個,個人感覺很完美,盡管老師說用的是鄰接表而不是多重表,太簡單,但還不錯,界面輸入過程比較繁瑣,要嚴格按照提示來輸入,是無向圖,等級太低,沒辦法把執行結果粘出來,應該能看懂吧

Ⅳ 有些圖論題數據太大無法用鄰接矩陣,所以請教教我怎麼用數組模擬鄰接表建圖(帶權)。(C/C++代碼)

暫且與例題一起的
路徑(netbar.pas)

綿陽中學以人數眾多而聞名。三個年級共有 10000 多人,學生多了附近的網吧也多。
Mzoiers 都熱衷於 Dota,可學校的機子配置相當差(評測伺服器除外),根本不能玩
Dota,那就只有去網吧。星期天到星期五都是晚上 10:20 才下晚自習,幾乎沒時間玩。
然而星期六下午放假是絕好的時間,但是學校人多啊,一放學去網吧的人就開始狂奔,競爭
之激烈,搶到機子的難度非常之大。往往在我們到達網吧之前都坐滿了。
學校到網吧的路是錯綜復雜的,以致於到一個自己想去的網吧都有非常多的路線可以選
擇,而路線的長度又不相同,這樣就決定了要花費的時間,因此想要盡快到達,選擇一條最
佳的線路是很有必要的。
【問題描述】
為了簡化問題,我們把學校與周邊的網吧看做圖中的頂點,學校與網吧,網吧與網吧之
間的路線看做邊,每個邊都有一個權,表示我們走完這條路的時間,由於放學人流量大,如
果反向走會有危險,因此這是一個有向圖。
我的學校在 S 點,想要去的網吧在 T 點。你的任務就是選擇一條最佳路線,使得從
學校到目的地網吧的時間最短,你只需要輸出最短到達時間即可。
【輸入文件】
netbar.in 中共有 M+2 行數據
第一行兩個整數 N,M,表示點數和邊數。
然後 M 行每行 3 個正整數(u,v,t),表示有一條可由 u 到 v 耗時為 t 的邊。
最後一行兩個正整數 S、T。
【輸出文件】
netbar.out 中,只有一行,一個整數表示最短時間。如果 S、T 之間不存在通路則輸
出「No Solution!」(雙引號不輸出,「!」為西文標點)。
【輸入樣例】
4 4
1 2 3
2 4 10
1 3 5
3 4 5
1 4
【輸出樣例】
10
【數據規模】
對於 30%的數據保證有 1<N<=1000,1<=M<=1000;
對於全部的數據保證有 1<N<=10000,1<=M<=100000。

解題思路:
題目可以抽象為輸入n個頂點,e條邊的有向圖,再讀入源點S和目標點T,求S到T的最短路。輸入規模:1<N<=10000,1<=M<=100000。
最短路有三種方法:floyd,dijsktra,spfa。如果用floyd,時間性能為O(n3) , 只能通過1000以內的數據;用dijkstra,時間性能為O(n2) ,只能通過10000以內的數據,且用鄰接矩陣存儲時,10000*10000*4個位元組,總內存達到380多MB,會超內存。用spfa演算法,時間性能為O(kM),能通過所有測試數據,k的值平均為2,表示頂點入隊的平均次數。此時,可以採用數組模擬鏈表的存邊方法,開一個邊的一維數組,把所有邊存儲起來。如對於如下輸入數據:
5 7
1 2 2
1 5 8
1 3 1
1 4 3
2 5 3
3 5 1
4 3 2
1 5
下面這個圖的數組模擬鏈表的形式存儲邊,把從某個頂點出來的所有邊通過鏈表的形式,鏈接起來,就象存儲普通有序樹一樣,右兒子掛到左兒子下面。這里的操作原理是,處理某個頂點出來的邊時,下一條邊掛到前一條邊,如下圖,第一條邊指向0,後面的邊都指向前一條邊,所以,在處理某個頂點相連的邊的松馳操作時,可以很方便的處理以該頂點連出去的邊,當指向0時,則以該 頂點出去的松馳操作完成。

program netbar;
var
list,dis:array [0..10000] of longint; //list存儲當前邊的指針,dis存儲各點到源點的最短路
next,toit,cost,q:array [0..100000] of longint;//next存儲當前邊指向前一條邊的位置,toit表示當前邊的出點,cost表示當前邊的邊權
n,m,i,a,b,c,s,e,tot:longint;
flag:array [0..10000] of boolean;
procere add(a,b,c:longint);//數組模擬鏈表的添邊的方法
begin
inc(tot); //邊的數目
toit[tot]:=b; //當前邊的出點頂點標號
cost[tot]:=c; //當前邊的權值
next[tot]:=list[a]; //當前邊指向前一條邊的位置,如果當前邊是頂點a的讀入的第一條邊,則它指向前面第0條邊,表示next[tot]:=0。
list[a]:=tot; //從入點a引出的邊的編號存儲給lsit[a]
end;
procere SPFA;
var
i,head,tail,v,k:longint;
begin
fillchar(flag,sizeof(flag),true);
for i:=1 to n do dis[i]:=maxlongint;
head:=1; tail:=1; q[1]:=s; dis[s]:=0; flag[s]:=false;//源點s入隊
repeat
v:=q[head]; k:=list[v]; //隊列頭出隊,k存儲當前v頂點的邊的編號
while k<>0 do //處理v的所有邊,直至邊指向0,即第一條邊也處理了
begin
if dis[v]+cost[k]<dis[toit[k]] then //松馳操作
begin
dis[toit[k]]:=dis[v]+cost[k]; //松馳成功
if flag[toit[k]] then //入隊
begin
inc(tail); q[tail]:=toit[k]; flag[toit[k]]:=false;
end;
end;
k:=next[k]; //處理頂點v的前一條邊
end;
flag[v]:=true;
inc(head);
until head>tail;
end;
begin
assign(input,'netbar.in'); reset(input);
assign(output,'netbar.out'); rewrite(output);
fillchar(list,sizeof(list),0);
fillchar(next,sizeof(next),0);
fillchar(toit,sizeof(toit),0);
fillchar(cost,sizeof(cost),0);
tot:=0;
readln(n,m);
for i:=1 to m do
begin readln(a,b,c); add(a,b,c); end;
readln(s,e);
SPFA;
if dis[e]<maxlongint then writeln(dis[e])
else writeln('No Solution!');
close(input); close(output);
end.

當N的頂點規模達到10000時,如果用鄰接矩陣存儲圖,容易超內存,且1個億的運算次數在1S的時限內不一定出得來。

不好意思 這邊只有PASCAL 的 暫且將就吧 c語言的MS沒有額……

Ⅵ 數據結構,如何根據鄰接表畫深度,廣度優先生成樹

深搜中枚舉時由大到小就是這個結果。

#include"stdio.h"

#include"stdlib.h"

#define MaxVertexNum 100 //定義最大頂點數

typedef struct{

char vexs[MaxVertexNum]; //頂點表

int edges[MaxVertexNum][MaxVertexNum]; //鄰接矩陣,可看作邊表

int n,e; //圖中的頂點數n和邊數e

}MGraph; //用鄰接矩陣表示的圖的類型

//=========建立鄰接矩陣=======

void CreatMGraph(MGraph *G)

{

int i,j,k;

char a;

printf("Input VertexNum(n) and EdgesNum(e): ");

scanf("%d,%d",&G->n,&G->e); //輸入頂點數和邊數

scanf("%c",&a);

printf("Input Vertex string:");

G->vexs[i]=a; //讀入頂點信息,建立頂點表

}

for(i=0;i<G->n;i++)

for(j=0;j<G->n;j++)

G->edges[i][j]=0; //初始化鄰接矩陣

printf("Input edges,Creat Adjacency Matrix ");

for(k=0;k<G->e;k++) { //讀入e條邊,建立鄰接矩陣

scanf("%d%d",&i,&j); //輸入邊(Vi,Vj)的頂點序號

G->edges[i][j]=1;

G->edges[j][i]=1; //若為無向圖,矩陣為對稱矩陣;若建立有向圖,去掉該條語句

}

//=========定義標志向量,為全局變數=======

typedef enum{FALSE,TRUE} Boolean;

Boolean visited[MaxVertexNum];

//========DFS:深度優先遍歷的遞歸演算法======

void DFSM(MGraph *G,int i)

visited[i]=TRUE; //置已訪問標志

for(j=0;j<G->n;j++) //依次搜索Vi的鄰接點

if(G->edges[i][j]==1 && ! visited[j])

DFSM(G,j); //(Vi,Vj)∈E,且Vj未訪問過,故Vj為新出發點

void DFS(MGraph *G)

{

int i;

for(i=0;i<G->n;i++)

visited[i]=FALSE; //標志向量初始化

for(i=0;i<G->n;i++)

if(!visited[i]) //Vi未訪問過

DFSM(G,i); //以Vi為源點開始DFS搜索

}

//==========main=====

void main()

{

//int i;

MGraph *G;

G=(MGraph *)malloc(sizeof(MGraph)); //為圖G申請內存空間

CreatMGraph(G); //建立鄰接矩陣

printf("Print Graph DFS: ");

DFS(G); //深度優先遍歷

printf(" ");

}

(6)樹可以用鄰接矩陣存儲擴展閱讀:

圖的鄰接表存儲方法跟樹的孩子鏈表示法相類似,是一種順序分配和鏈式分配相結合的存儲結構。如這個表頭結點所對應的頂點存在相鄰頂點,則把相鄰頂點依次存放於表頭結點所指向的單向鏈表中。

如詞條概念圖所示,表結點存放的是鄰接頂點在數組中的索引。對於無向圖來說,使用鄰接表進行存儲也會出現數據冗餘,表頭結點A所指鏈表中存在一個指向C的表結點的同時,表頭結點C所指鏈表也會存在一個指向A的表結點。

Ⅶ 存儲圖時,哪些情況用鄰接矩陣方便

如果邊比較少的情況下,用鄰接矩陣節省存儲空間。邊比較多就可以選擇鄰接矩陣

Ⅷ 求無向連通圖的生成樹(用c語言設計程序)

不知道你要的是不是這個 完整實現如下: #define INFINITY 65535typedef int status;# include <stdio.h># include <stdlib.h># include <conio.h># include "string.h"# define maxlen 10typedef struct{ char vexs[maxlen][maxlen];/*頂點信息集合,我們用它來存入頂點名字*/ int vexnum,arcnum;/*頂點數和邊數*/ int arcs[maxlen][maxlen];/*鄰接矩陣*/}graph;//定位輸入節點的名稱int LocateVex(graph G,char u[maxlen]){int i;for(i=0;i<G.vexnum;++i) if(strcmp(u,G.vexs[i])==0) return i; return -1;} void prim(graph &g)/*最小生成樹*/{ int i,j,k,min,w,flag; int lowcost[maxlen];/*權值*/ int closet[maxlen];/*最小生成樹結點*/ char va[maxlen],vb[maxlen]; //初始化鄰接矩陣 //printf("請輸入頂點數和邊數:\n"); //scanf("%d%d",&g.vexnum,&g.arcnum); g.vexnum=6; g.arcnum=10; printf("請輸入頂點信息(我們這里指名字):\n"); for(int j=0;j<g.vexnum;j++) scanf("%s",g.vexs[j]); for(i=0;i<g.vexnum;++i) for(j=0;j<g.vexnum;++j)//初始化鄰接矩陣 { g.arcs[i][j]=INFINITY; //任意兩個頂點間距離為無窮大。 }//for /*printf("請輸入%d條弧的弧尾 弧頭 權值(以空格為間隔)\n",g.arcnum); for(k=0;k<g.arcnum;++k) { scanf("%s%s%d%*c",va,vb,&w);//用%*c吃掉回車符 i=LocateVex(g,va); //注意,這里定義的是char va[5],也就是說va是首地址 j=LocateVex(g,vb); g.arcs[i][j]=w; //無向網 g.arcs[j][i]=w; //無向網 }//for */ g.arcs[0][1]=6; g.arcs[1][0]=6; g.arcs[0][2]=1; g.arcs[2][0]=1; g.arcs[0][3]=5; g.arcs[3][0]=5; g.arcs[1][2]=5; g.arcs[2][1]=5; g.arcs[1][4]=3; g.arcs[4][1]=3; g.arcs[2][3]=5; g.arcs[3][2]=5; g.arcs[2][4]=6; g.arcs[4][2]=6; g.arcs[2][5]=4; g.arcs[5][2]=4; g.arcs[3][5]=2; g.arcs[5][3]=2; g.arcs[4][5]=6; g.arcs[5][4]=6; printf("最小生成樹的邊為:\n"); for(i=1;i<g.vexnum;i++) { lowcost[i]=g.arcs[0][i]; closet[i]=1; } closet[0]=0; //初始v1是屬於集合U的,即設它是最小生成樹中節點的一員 j=1; //V是頂點集合 for(i=1;i<g.vexnum;i++) { min=lowcost[j]; k=i; for(j=1;j<g.vexnum;j++) if(lowcost[j]<min&&closet[j]!=0) { min=lowcost[j]; k=j; //記錄當前要加入集合U的節點號 }//if if(i==1) flag=0; else flag=closet[k]; //還沒有加入集合U的節點的closet[]值是 //記錄了上一次加入集合U的節點號 closet[k]=0; //將剛剛找到的點加入到集合U中 printf("(%s,%s),",g.vexs[k],g.vexs[flag]);//輸出剛剛找到的最小生成樹樹枝 for(j=1;j<g.vexnum;j++) if(g.arcs[k][j]<lowcost[j]&&closet[j]!=0) { lowcost[j]=g.arcs[k][j]; //更新lowcost[]的值,且在還沒有加入U集合的 //的closet[]中記錄剛剛加入U集合的節點號以備 //下一循環中輸出用 closet[j]=k; } }} int main(){graph g;prim(g);}