●•٠سروده های استادشهریار٠•●

●•٠سروده های استادشهریار٠•●

شهریارا تو به شمشیر قلم در همه آفاق - به خدا ملک دلی نیست که تسخیر نکردی *"به شعرت شهریارا بیدلان تا عشق میورزند ... نسیم وصل را ماند نوید طبع دیوانت"
●•٠سروده های استادشهریار٠•●

●•٠سروده های استادشهریار٠•●

شهریارا تو به شمشیر قلم در همه آفاق - به خدا ملک دلی نیست که تسخیر نکردی *"به شعرت شهریارا بیدلان تا عشق میورزند ... نسیم وصل را ماند نوید طبع دیوانت"

الگوریتم دایجسترا،کاربردها و سورس برنامه

الگوریتم دایجسترا همراه توضیحات و پیچیدگی زمانی

Dijkstra_Animation

در نظریه گراف، الگوریتم دیکسترا (به انگلیسی: Dijkstra’s algorithm)‏ یکی از الگوریتم‌های پیمایش گراف است که توسط دانشمند هلندی علوم رایانه، اِدْسْخِر دِیْکْسْترا در سال ۱۹۵۹ ارایه شد.

روند الگوریتم دیکسترا مطابق زیر می باشد :

۱- انتخاب راس مبدا

۲- مجموعه ی S ، شامل رئوس گراف ، معین می شود. در شروع، این مجموعه تهی بوده و با پیشرفت الگوریتم، این مجموعه رئوسی که کوتاه ترین مسیر به آن ها یافت شده است را در بر می گیرد.

۳- راس مبدا با اندیس صفر را در داخل S قرار می دهد.

۴- برای رئوس خارج از S ، اندیسی معادل ، طول یال + اندیس راس قبلی ، در نظر می گیرد . اگر راس خارج از مجموعه دارای اندیس باشد، اندیس جدید کمترین مقدار از بین اندیس قبلی و طول یال + اندیس راس قبل ، می باشد.

۵- از رئوس خارج مجموعه، راسی با کمترین اندیس انتخاب شده و به مجموعه ی S اضافه می گردد.

۶- این کار را دوباره از مرحله ی ۴ ادامه داده تا راس مقصد وارد مجموعه ی S شود.

در پایان اگر راس مقصد دارای اندیس باشد، اندیس آن نشان دهنده ی مسافت بین مبدا و مقصد می باشد. در غیر این صورت هیچ مسیری بین مبدا و مقصد موجود نمی‌باشد.

همچنین برای پیدا کردن مسیر می توان اندیس دیگری برای هر راس در نظر گرفت که نشان دهنده ی راس قبلی در مسیر طی شده باشد. بدین ترتیب پس از پایان اجرای الگوریتم، با دنبال کردن رئوس قبلی از مقصد به مبدا، کوتاه ترین مسیر بین دو نقطه نیز یافت می شود.

ر حین اجرای الگوریتم دو چیز به طور ضمنی نگهداری می‌شود. یکی مجموعهٔ S از رأس‌هایی که وزن کوتاه‌ترین مسیر از مبدأ تا آن‌ها مشخص شده و دیگری دنبالهٔ d که برای هر رأس v، مقدار d_v برابر وزن کوتاه‌ترین مسیر از مبدأ تا v است به شرطی که تمام رأس‌های این مسیر به جز v از رئوس داخل S باشند. S در ابتدا تهی و مقادیر d برای همهٔ رئوس به غیر از مبدأ بی‌نهایت است و مقدار آن برای مبدأ صفر گذاشته می‌شود. الگوریتم در هر مرحله رأسی خارج S را که d برای آن کمترین است انتخاب و به مجموعهٔ S اضافه می‌کند و سپس مقادیر d را برای رئوس همسایهٔ آن رأس به‌روز می‌نماید. در صورتی که نیاز به تشکیل درخت کوتاه‌ترین مسیر باشد، الگوریتم می‌بایست دنبالهٔ \pi را که \pi_v پدر رأس v در درخت کوتاه‌ترین مسیر است، به همراه دنبالهٔ d به‌روز کند.

پیچیدگی زمانی

در ساده‌ترین پیاده‌سازی الگوریتمِ دیکسترا، داده‌ها در آرایه یا لیست پیوندی ذخیره می‌شوند که بدین ترتیب مینیمم مقدار d برای رئوس خارج S با الگوریتمی خطی یافت می‌شود. در این حالت پیچیدگی زمانی O(|V|^2+|E|) خواهد بود، چراکه در گراف بدون جهت هر یال دقیقاً دوبار و در گراف جهت‌دار هر یال دقیقاً یک بار پیمایش می‌شود و هم‌چنین پیدا کردن مینیمم، (|O(|V زمان می‌خواهد که این مینیمم پیدا کردن |V| بار تکرار خواهد شد. برای گراف‌های پراکنده (یعنی گراف‌هایی که خیلی کمتر از مجذور |V| یال دارند) الگوریتم دیکسترا با نگهداری گراف در فهرست مجاورت و استفاده از صف اولویت‌دار (Priority-Queue) (برای پیدا کردن مینیمم) با پیچیدگی زمانی O((|V|+|E|)log|V|) پیاده‌سازی می‌شود. در صورت استفاده از نگهدارندهٔ فیبوناتچی (Fibonacci heap) به جای صف اولویت‌دار، پیچیدگی زمانی با تحلیل جمعی (Amortized analysis) به O(|E|+|V|log|V|) بهبود می‌یابد.

کاربردها

ز جمله مهمترین کاربرد های این روش می توان به محاسبه ی کوتاه ترین فاصله ی دو نقطه در یک شهر از طریق راه های زمینی اشاره نمود. برای محاسبه ی کوتاه ترین مسیر بین دو نقطه باید نقاط مورد نظر در یک نقشه را علامت گذاری کرد و با استفاده از مشخصات نقاط(طول، عرض و ارتفاع) فاصله ی دو نقطه را در هر بار عملیات محاسبه نمود.توجه داریم که در ترافیک سرعت خودرو ها به شدت پایین آمده و این امر می تواند در انتخاب کوتاه ترین مسیر تاثیر گذار باشد چرا که ممکن است بین دو نقطه a,b راه های ۱و۲ موجود باشد که راه ۱ اتوبان و از خارج شهر و راه ۲ از داخل شهر عبور می کند. فرض کنید فاصله ی a,b از طریق راه ۱ حدود ۱۰ کیلومتر و از طریق راه ۲ حدود ۷ کیلومتر باشد ولی راه ۲ علی رقم فاصله ی کمتر دارای ترافیک سنگین است در نتیجه می توان انتظار داشت که در ساعات شلوغی استفاده از راه ۱ بهتر باشد.از آن جا که اساس محاسبات در این روش بر پایه ی فاصله بین دو نقطه است می توان کاهش سرعت را با افزایش فواصل هم ارز نمود چرا که اگر رابطه ی سرعت و فاصله را خطی در نظر بگیریم (D=V.T)تاثیر کاهش سرعت و افزایش مسافت یکسان است.از این رو لازم است تا ضرایب تعدیلی در فواصل بین نقاط ضرب شده و این مسائل را در محاسبات لحاظ کرد. از جمله مهم ترین این ضرایب می توان به ۳ مورد زیر اشاره نمود: ۱-ضریب ترافیک و شلوغی ۲-ضریب عرض معبر ۳-ضریب شیب که نشانگر افت سرعت در سر بالایی هااست. گرچه تعیین این ضرایب برای نقاط مختلف شهر نیازمند کارشناسان متخصص ترافیک و بررسی های آماری دقیق می باشد ولی می توان انتظار داشت که در اکثر موارد این ضرایب بین مقادیر ۱ تا ۲ بسته به شرایط تغییر کنند.

 

کد سورس الگوریتم دایجسترا به زبان #C

using System;

using System.Collections.Generic;

using System.Collections;

using System.Linq;

using System.Text;

 

namespace DijktrasAlgorithm

{

class Program

{

///writing by navid

/// site http://daneshju-club.com if you want to use the source code

static List Nodes = new List();

static Dictionary NodesIndex = new Dictionary();

static List Edges = new List();

static int SizeEdges = 0;

static int SizeNodes = 0;

static string StartNode;

class node

{

public string name;

public string pre;

public int Dist;

public bool vis;

public node(string NodeName)

{

name = NodeName;

Dist = -1;

vis = false;

}

}

static public void AddNode(string NodeName)

{

node temp = new node(NodeName);

Nodes.Add(temp);

NodesIndex.Add(NodeName, Nodes.Count() - 1);

}

class edge

{

public string N1;

public string N2;

public int Dist;

public edge(string Node1, string Node2, int EdgeVal)

{

N1 = Node1;

N2 = Node2;

Dist = EdgeVal;

}

}

static public void AddEdge(string Node1, string Node2, int EdgeVal)

{

edge temp = new edge(Node1, Node2, EdgeVal);

Edges.Add(temp);

}

static void SetStartNode(string name)

{

Nodes[NodesIndex[name]].Dist = 0;

SizeNodes = Nodes.Count();

SizeEdges = Edges.Count();

StartNode = name;

}

static int VisitClosetNode()

{

int index = 0;

int Dist = 0;

for (int i = 0; i < SizeNodes; ++i)

{

if (!Nodes[i].vis && Nodes.Dist >= 0)

{

Dist = Nodes[i].Dist;

index = i;

break;

}

}

for (int i = 0; i < SizeNodes; ++i)

{

if (Nodes[i].Dist < Dist && !Nodes.vis && Nodes[i].Dist >= 0)

{

Dist = Nodes[i].Dist;

index = i;

}

}

Nodes[index].vis = true;

return index;

}

static void GetAllAdjcentNodes(string N, List AdjNodes)

{

for (int i = 0; i < SizeEdges; ++i)

{

if (Edges[i].N1 == N && !(Nodes[(NodesIndex[Edges.N2])].vis))

{

AdjNodes.Add(Edges[i].N2);

}

else if (Edges[i].N2 == N && !(Nodes[NodesIndex[Edges.N1]].vis))

{

AdjNodes.Add(Edges[i].N1);

}

}

}

static bool EdgeConnectsNodes(edge E, string N1, string N2)

{

return (E.N1 == N1 && E.N2 == N2 || E.N1 == N2 && E.N2 == N1);

}

static int GetDistance(string N1, string N2)

{

for (int i = 0; i < SizeEdges; ++i)

{

if (EdgeConnectsNodes(Edges[i], N1, N2))

{

return Edges[i].Dist;

}

}

return -1;

}

static int GetNumOfUnVisNodes()

{

int NOUVN = 0;

for (int i = 0; i < SizeNodes; ++i)

{

if (!Nodes[i].vis)

{

++NOUVN;

}

}

return NOUVN;

}

static void Dijkstras()

{

while (GetNumOfUnVisNodes() > 0)

{

node ClosetsNode = Nodes[VisitClosetNode()];

List AdjNodes = new List();

GetAllAdjcentNodes(ClosetsNode.name, AdjNodes);

int SizeAdj = AdjNodes.Count();

for (int i = 0; i < SizeAdj; ++i)

{

node AdjNode = Nodes[NodesIndex[AdjNodes[i]]];

int Distance = ClosetsNode.Dist + GetDistance(ClosetsNode.name, AdjNodes[i]);

if (AdjNode.Dist >= 0)

{

if (Distance < AdjNode.Dist)

{

AdjNode.Dist = Distance;

AdjNode.pre = ClosetsNode.name;

}

}

else

{

AdjNode.Dist = Distance;

AdjNode.pre = ClosetsNode.name;

}

}

}

}

static void GetPathTo(string N, List Path)

{

string CN = N;

while (CN != StartNode)

{

string Temp = CN;

Path.Insert(0, Temp);

CN = Nodes[NodesIndex[CN]].pre;

}

Path.Insert(0, StartNode);

}

static void Main(string[] args)

{

AddNode("a");

AddNode("b");

AddNode("c");

AddNode("d");

AddNode("e");

AddNode("f");

AddNode("g");

 

AddEdge("a", "c", 10);

AddEdge("a", "d", 19);

AddEdge("b", "c", 4);

AddEdge("c", "d", 4);

AddEdge("b", "f", 41);

AddEdge("c", "e", 20);

AddEdge("e", "f", 17);

AddEdge("d", "g", 30);

AddEdge("g", "f", 4);

 

SetStartNode("a");

 

Dijkstras();

 

List Path = new List();

GetPathTo("f", Path);

int Size = Path.Count();

for (int i = 0; i < Size; ++i)

{

Console.WriteLine(Path[0]);

Path.Remove(Path[0]);

}

Console.Read();

}

}

}