本文着重于算法的实现,对于理论部分可自行查看有关资料可以简略参考该博文:http://blog.csdn.net/u013007900/article/details/50379135
本文代码部分基于C实现,源码如下:
 /*****************************************************************************
 **    Copyright: NEW NEU laboratory
 **    File name: CTSP
 **    Description:禁忌搜索算法解决TSP问题
 **    Author: 1702-GCJ
 **    Version: 1.1
 **    Date: 2017/10/3
 **    History: 无
 ** Modification: IsFindTabu(Queue * Q,const Tabu *item)
 *****************************************************************************/

 #include"stdio.h"
 #include"stdlib.h"
 #include"string.h"
 #include "time.h"

 #define CityNum         31       //城市的数量
 #define TabuLength     21     //禁忌表长度(根号下的 种类)
 #define Neighbor        400     //邻居个数
 #define MaxNG            400    //迭代次数    

 ;             //当前迭代次数
 ;            //渴望水平 (即最短距离) 

 typedef int ElementType;
 ElementType **Distance;        //存储各个城市之间的距离矩阵的指针 数据都是取整的 

 /***************************************************************************************读取数据区******************************************/

 /*************************************************
 **Function: MemBlockCity
 **Description: 申请存储城市距离空间
 **Calls: 无
 **Called By: ReadDataTxt()
 **Input: 无
 **Output: 无
 **Return: 指向存储城市距离空间的指针
 **Others: 用完需要释放掉相应内存
 *************************************************/
 ElementType ** MemBlockCity();

 /*************************************************
 **Function: PrintCityDistance
 **Description: 显示Distance信息
 **Calls: 无
 **Called By: main()
 **Input: Distance 全局变量的指针
 **Output: 无
 **Return: void
 **Others: 无
 *************************************************/
 void PrintCityDistance( ElementType **  distance);

 /*************************************************
 **Function: ReadDataTxt
 **Description: 从txt文档中读取数据
 **Calls: MemBlockCity()
 **Called By: main
 **Input: 无
 **Output: 无
 **Return: void
 **Others: 里面直接用的全局变量 指针Distance
 *************************************************/
 void ReadDataTxt();

 /*************************************************
 **Function: WriteDataTxt
 **Description: 将Distance全局数组数据写到txt文档中去
 **Calls: 无
 **Called By: main()
 **Input: 无
 **Output: 无
 **Return: void
 **Others: 里面用到了宏值CityNum值
 *************************************************/
 void WriteDataTxt();
 /**********************************************************************************禁忌表操作区*******************************************/
 typedef struct _Tabu{
     int smallNum;
     int bigNum;    //存储数量大的元素
 }Tabu; //禁忌表结构 

 typedef struct _Queue{
     Tabu *tabuList;//队列空间指针
     int rear;        //指向尾部
     int front;        //指向队列的头部
     int maxSize;    //记录队列的最大个数
     int count;        //记录资源个数 判断队列空满
     int tabuIndex;    //在禁忌表中找到禁忌元素时 存储该值在禁忌表中的位置
 }Queue;//循环队列的形式 

 /*************************************************
 **Function: CreateQueue
 **Description: malloc一个禁忌表队列并初始化
 **Calls: 无
 **Called By: main()
 **Input: tabuLength 禁忌表数据长度
 **Output: 无
 **Return: Queue * 队列变量
 **Others: 里面用到了宏值CityNum值 ,用完需要释放掉相应内存
 *************************************************/
 Queue * CreateQueue(int tabuLength);

 /*************************************************
 **Function: UpdateTabu
 **Description: 更新禁忌表
 **Calls: IsFindTabu()
 **Called By: TSP()
 **Input: Q 禁忌表队列 item 加入禁忌表的Tabu结构的变量
 **Output: 无
 **Return: void
 **Others:
 *************************************************/
 void UpdateTabu(Queue *Q,Tabu *item);

 /*************************************************
 **Function: IsFindTabu
 **Description: 禁忌表中是否找到这个元素
 **Calls: 无
 **Called By: UpdateTabu() TSP()
 **Input: Q 禁忌表队列 item 判断其是否在禁忌表中的Tabu结构的变量的指针
 **Output: 无
 **Return: 0 没有找到这个元素 1 找到这个元素了
 **Others:
 *************************************************/
 static int IsFindTabu(Queue * Q,const Tabu *item);

 /****************************************************************************2Opt邻域+TSp核心算法*********************************************/
 //定义解的存储类型 向量形式
 typedef struct _Solve{
     ElementType *initSolution;            //初始解
     ElementType *currentSolution;        //当前解
     ElementType * optimalSolution;    //最优解
     ElementType *tempSolution;            //临时解
     ElementType lastdistance;             //上次记录的总距离
     ElementType  initdistance;            //定义初始距离
 }StrSolve;
 typedef struct _MotionTable{
     Tabu  tabu;                                //存储改变的元素
     ElementType changedistance;        //改变的距离
 }MotionTable;//记录2opt邻域移动信息 

 StrSolve * SolutionSpace ;             //解空间(包含当前解和初始解)指针
 MotionTable *motionTable;                //移动元素信息 (一个表格) 

 /*************************************************
 **Function: CreateMotionStruct
 **Description: 创建并初始化2-Opt 移动信息表格
 **Calls: 无
 **Called By:  Init2Opt()
 **Input: neighbor  邻居数量
 **Output: 无
 **Return: MotionTable *指针变量
 **Others: 不用这块内存的时候要释放掉 !
 *************************************************/
 MotionTable* CreateMotionStruct(int neighbor);

 /*************************************************
 **Function: CreateSolutionSpace
 **Description: 创建并初始化解空间
 **Calls: 无
 **Called By:  Init2Opt()
 **Input: cityNum  城市数量
 **Output: 无
 **Return: StrSolve  *指针变量
 **Others: 不用这块内存的时候要逐一释放掉 !
 *************************************************/
 StrSolve *CreateSolutionSpace(int cityNum);

 /*************************************************
 **Function: GetInitSolution
 **Description: 获得初始解
 **Calls: 无
 **Called By:  Init2Opt()
 **Input: StrSolve * 指针变量
 **Output: 无
 **Return: StrSolve  *指针变量
 **Others: 这里在初始化解的时候可以用其他元启发式算法得出一个较好的解  !
 *************************************************/
 void GetInitSolution(StrSolve * strSolve);

 /*************************************************
 **Function: Init2Opt
 **Description: 初始化TSP需要用的值
 **Calls: CreateMotionStruct()  CreateSolutionSpace()  GetInitSolution()
 **Called By:  main
 **Input: 无
 **Output: 无
 **Return: void
 **Others: 这里在初始化解的时候可以用其他元启发式算法得出一个较好的解  ! 不知道为什么只能在Main函数中调用否则 会出现段错误
 *************************************************/
 void Init2Opt();

 /*************************************************
 **Function: FindPosition
 **Description: 在数组中找到指定元素值的位置
 **Calls:
 **Called By:  Get2OptChangeDistance()  TSP()
 **Input: solution 一维数组指针  tabu  Tabu结构指针
 **Output: 无
 **Return: void
 **Others: 这里是从solution[1]开始查找到的!
 *************************************************/
 static void FindPosition(const ElementType * solution,Tabu *tabu);

 /*************************************************
 **Function: FindPosition
 **Description: 获得2邻域变化值
 **Calls: FindPosition()
 **Called By:  Get2optSolution()
 **Input:  tabu  Tabu结构指针  solution 一维数组指针
 **Output: 无
 **Return: ElementType 2邻域城市变化值
 **Others: 返回的值越小越好 !
 *************************************************/
 static ElementType Get2OptChangeDistance(Tabu * tabu,const ElementType * solution);

 /*************************************************
 **Function: Get2optSolution
 **Description: 得到1个2邻域解 将移动元素,及其导致路径的变化值 存储到移动表中
 **Calls: Get2OptChangeDistance()
 **Called By:  TSP()
 **Input:  strSolve 解空间指针  motiontable 移动表指针
 **Output: 无
 **Return: void
 **Others: 随机数要注意!
 *************************************************/
 void Get2optSolution(const StrSolve * strSolve,MotionTable *motiontable );

 /*************************************************
 **Function: Insert_Sort
 **Description: 按从小到大排序 插入排序 将制定的类数组变量 的内容进行排序
 **Calls: 无
 **Called By:  FindBestMotionValue()
 **Input:    motiontable 移动表指针  n为类数组 元素个数
 **Output: 无
 **Return: void
 **Others:
 *************************************************/
 void Insert_Sort (MotionTable * motiontable,int n);

 /*************************************************
 **Function: FindBestMotionValue
 **Description: 找到移动表中最小的值 即为最优值
 **Calls: Insert_Sort()
 **Called By:  TSP()
 **Input:    motiontable 移动表指针
 **Output: 无
 **Return: MotionTable *型的指针 存储移动表中最好值的表格指针
 **Others:
 *************************************************/
 MotionTable * FindBestMotionValue( MotionTable * motiontable);

 /*************************************************
 **Function: GetInitLevel
 **Description: 获取初始解的渴望水平
 **Calls:
 **Called By:  TSP()
 **Input:    distance 存储城市的矩阵指针 initSolution 初始解指针
 **Output: 无
 **Return: 初始解的渴望水平
 **Others:
 *************************************************/
 int GetInitLevel( ElementType **distance,ElementType * initSolution);

 /*************************************************
 **Function: TSP
 **Description: TSP核心算法
 **Calls: GetInitLevel()
 **Called By:  TSP()  Get2optSolution()  FindBestMotionValue()  UpdateTabu()  FindPosition()  memcpy()
 **Input:    distance 存储城市的矩阵指针 solutionSpace 解空间指针 motiontable 移动表 desireLevel 渴望水平 queue 禁忌表队列指针
 **Output: 最优解信息
 **Return: void
 **Others:
 *************************************************/
 void TSP(  ElementType **distance, StrSolve * solutionSpace ,MotionTable *motiontable,int *desireLevel,Queue *queue);

 /*************************************************
 **Function: MemFree
 **Description: 释放申请的动态内存
 **Calls: free()
 **Called By:  main()
 **Input: distance 存储城市距离的变量指针  queue 禁忌表队列  motiontable 移动表的指针  strSolve  解空间的指针
 **Output: 无
 **Return: void
 **Others: 这里也可以一步一步的释放掉 各自的指针 因为就用一个.c所以释放内存的操作都在这里进行
 *************************************************/
 void MemFree(ElementType ** distance,Queue *queue,MotionTable *motiontable,StrSolve *strSolve);

 /*******************************************************************************MAIN函数*************************************/
 int main(int argc,char *argv[])
 {
 //    Tabu item;
     clock_t start, finish;
     double  duration;
     Queue * queue = CreateQueue(TabuLength); //创建一个禁忌表队列 本身就初始化好了
     Init2Opt();//初始化相关
     // 设置随机数种子 为以后使用rand()做准备
    srand((unsigned ));

     start = clock();
     ReadDataTxt(Distance);//必须放在前面  读取数据后 才能操作
 //    PrintCityDistance(Distance); //显示二维数组的数据 只显示5X5
 // WriteDataTxt(Distance);//将distance 数据写入txt
     TSP( Distance,SolutionSpace ,motionTable,&DesireLevel,queue);    

 ////    //将得到的最优解 从新用TSP算法算
 //    memcpy( SolutionSpace->initSolution,SolutionSpace->optimalSolution,sizeof(ElementType)*CityNum ); //将临时解空间值复制到当前解空间
 //    printf("\n新初始解的渴望水平:%d  \n",GetInitLevel(Distance,SolutionSpace->optimalSolution));
 //    TSP( Distance,SolutionSpace ,motionTable,&DesireLevel,queue);
 //
     finish = clock();
     duration = (double)(finish - start) / CLOCKS_PER_SEC;
     printf("\n           TSP算法运行时间:%.4f秒       \n",duration);
     MemFree(Distance, queue,motionTable,SolutionSpace);
    ;
 } 

 /************************************************************************读取数据区***********************************************/ 

 /*************************************************
 **Function: MemBlockCity
 **Description: 申请存储城市距离空间
 **Calls: 无
 **Called By: ReadDataTxt() 在txt文档中读取数据
 **Input: 无
 **Output: 无
 **Return: 指向存储城市距离空间的指针
 **Others: 无
 *************************************************/
 ElementType ** MemBlockCity()
 {
     ElementType ** Distance;
     ;

     //动态申请一块内存存储城市之间的数据
     Distance = (ElementType **)malloc(sizeof(ElementType *)*CityNum);
     ;i< CityNum ; i++){
         Distance[i] = (ElementType *)malloc(sizeof (ElementType )* CityNum);
     }
     return Distance;
 }

 /*************************************************
 **Function: PrintCityDistance
 **Description: 显示Distance信息 这里仅仅显示了CityNum-25个元素 因为屏幕显示不开
 **Calls: 无
 **Called By: main()
 **Input: Distance 全局变量的指针
 **Output: 无
 **Return: void
 **Others: 无
 *************************************************/
 void PrintCityDistance( ElementType **  distance)
 {
     int i,j;
     ; i< CityNum-;i++){
         ;j<CityNum-;j++)
             printf("%d ",distance[i][j]);
         printf("\n");
     }
 }

 /*************************************************
 **Function: ReadDataTxt
 **Description: 从txt文档中读取数据
 **Calls: MemBlockCity()
 **Called By: main()
 **Input: 无
 **Output: 无
 **Return: void
 **Others: 里面直接用的全局变量 指针Distance
 *************************************************/
 void ReadDataTxt()
 {
     //     FILE *fpRead=fopen("F:\\GCJ\\Desktop\\智能优化方法作业\\data.txt","r");
     FILE *fpRead=fopen("data.txt","r");  //从data.txt中读取数据
     int i,j;
     if(fpRead==NULL){
           printf("open file data.txt failed!\n");
        exit();
     }
     Distance = MemBlockCity();    //申请一块存储城市数量空间
     ;i<CityNum;i++){
         Distance[i][i] = ;
          ;j < CityNum;j++ ){
             fscanf(fpRead,"%d",&Distance[i][j]);//自动读取数据 只要自己能够控制好存储位置即可
             Distance[j][i] = Distance[i][j];
         }
     }
     fclose(fpRead);
 }

 /*************************************************
 **Function: WriteDataTxt
 **Description: 将Distance全局数组数据写到txt文档中去
 **Calls: 无
 **Called By: main()
 **Input: 无
 **Output: 无
 **Return: void
 **Others: 里面用到了宏值CityNum值
 *************************************************/
 void WriteDataTxt(ElementType **distance)
 {
     FILE *fpWrite;
     int i,j;
     fpWrite=fopen("F:\\GCJ\\Desktop\\智能优化方法作业\\data.txt","w");  //从data.txt中写数据
     ;i< CityNum;i++){
         ;j<CityNum;j++)
             fprintf(fpWrite,"%d ",distance[i][j]);//这里%d后面必须要有空格 否则 直接输出连续的数字
             fprintf(fpWrite,"\n");
     }
     fclose(fpWrite);
 }

 /**************************************************************禁忌表操作区*****************************************************/

 /*************************************************
 **Function: CreateQueue
 **Description: malloc一个禁忌表队列并初始化
 **Calls: 无
 **Called By: main()
 **Input: tabuLength 禁忌表数据长度
 **Output: 无
 **Return: Queue * 队列变量
 **Others: 里面用到了宏值CityNum值
 *************************************************/
 Queue * CreateQueue(int tabuLength)
 {
     Queue * queue = (Queue *)malloc(sizeof(struct _Queue));//申请一块队列变量
     //queue->tabuList =(ElementType *)malloc(sizeof(ElementType)*MaxSize);//申请一块数组空间
     queue->tabuList =(Tabu *)malloc(sizeof(Tabu)*tabuLength);//21的长度
     queue->front = ;
     queue->rear = ;//头尾 都为0
     queue->maxSize = tabuLength;
     queue->count =;
     queue->tabuList[].smallNum = ;
     queue->tabuList[].bigNum  = ;
     return queue;
 } 

 /*************************************************
 **Function: IsFindTabu
 **Description: 禁忌表中是否找到这个元素
 **Calls: 无
 **Called By: UpdateTabu() TSP()
 **Input: Q 禁忌表队列 item 判断其是否在禁忌表中的Tabu结构的变量的指针
 **Output: 无
 **Return: 0 没有找到这个元素 1 找到这个元素了
 **Others:
 *************************************************/
 static int IsFindTabu(Queue * Q,const Tabu *item)
 {
     Tabu tabu;
     int i;
      ; 

     //将要禁忌的值按顺序放在中间变量中 方便加入到禁忌表中
     if( (*item).bigNum >= (*item).smallNum ){
         tabu.bigNum = (*item).bigNum;
         tabu.smallNum = (*item).smallNum;
     }
     else{
         tabu.bigNum = (*item).smallNum;
         tabu.smallNum = (*item).bigNum;
     } 

     //查找禁忌表中是否有这个禁忌元素  没有的话 插入元素在头部 否则把这个元素加上惩罚政策加入到禁忌表的头部 其他依次降序
     for(i = Q->front; (i%TabuLength)!= Q->rear; ){//这个查找函数有问题了 因为循环队列的话 队列慢点话 rear = front  如何解决?
         if( (tabu.smallNum == Q->tabuList[i].smallNum ) && ( tabu.bigNum == Q->tabuList[i].bigNum )  ){
         //说明在禁忌表中找到这个元素了 那么就惩罚这个 放在最前面
         //把第一个元素放入 这个值 剩下的依次 递减排列
 //            printf("在禁忌表中找到了%d %d\n",tabu.bigNum,tabu.smallNum);

             //新加     记录位置
             Q->tabuIndex = i; 

             IsFindFlag  = ;
             return IsFindFlag ;    //表示不管了
         }
         if(++i >= TabuLength)//仅仅让i 在 0 - Tabulength范围内遍历
             i = ;
     }
     if( Q->count >= TabuLength ){//说明禁忌表满 那么rear值就需要访问了  否则不需要访问
         if( i%TabuLength == Q->rear )//因为循环队列寻找的时候 最后一个元素 无法通过for循环遍历到
         if( (tabu.smallNum == Q->tabuList[i].smallNum ) && ( tabu.bigNum == Q->tabuList[i].bigNum )  ){
 //            printf("找到了最新的了%d %d\n",tabu.smallNum,tabu.bigNum);    

             //新加     记录位置
             Q->tabuIndex = Q->rear; 

             IsFindFlag  = ;
             return IsFindFlag ;    //表示不管了
         }
     }

         return IsFindFlag;//之前这里就忘了加了 注意这点    !!
 }

 /*************************************************
 **Function: UpdateTabu
 **Description: 更新禁忌表
 **Calls: IsFindTabu()
 **Called By: TSP()
 **Input: Q 禁忌表队列 item 加入禁忌表的Tabu结构的变量的指针
 **Output: 无
 **Return: void
 **Others:
 *************************************************/
 void UpdateTabu(Queue *Q,Tabu *item)
 {
     Tabu tabu;
     Tabu temptabu;
     int i; 

     //将要禁忌的值按顺序放在中间变量中 方便加入到禁忌表中
     if( (*item).bigNum >= (*item).smallNum ){
         tabu.bigNum = (*item).bigNum;
         tabu.smallNum = (*item).smallNum;
     }
     else{
         tabu.bigNum = (*item).smallNum;
         tabu.smallNum = (*item).bigNum;
     }

     if( !IsFindTabu(Q,item) ){
         //如果没有找到  那么直接在队列插入这个元素
         if( Q->count < TabuLength ){ //说明队列不满 那就直接插入元素
             Q->count++ ;//最后满的时候为21个元素
             Q->tabuList[Q->rear++] = tabu;//在后面插入 然后从前面取出元素
             if( Q->rear >= TabuLength)//到了尾部的话 就直接从前面开始存储  尾部先存储后+1
                 --Q->rear ;//说明禁忌表满了的时候 让rear指向最后一个元素即可
         }
         else{//满了的话 就直接头部删除 尾部加入 //不是真正的删除 仅仅是释放掉这块存储空间
             if( ++Q->front >= TabuLength )
                 Q->front  =;
             if( ++Q->rear >= TabuLength)//到了尾部的话 就直接从前面开始存储  尾部先存储后+1
                 Q->rear = ;
             Q->tabuList[Q->rear]  = tabu;
         }
     }
     else{//在禁忌表中找到这个元素的时候 需要进行惩罚 将这个值放在头部,而该值前面的数依次向后排
         int j,k;
         j = Q->tabuIndex ;    //禁忌表中找到的该值的索引
         k = Q->front;            //禁忌表头部索引

         if( Q->tabuIndex >= Q->front  ){

             //说明禁忌表没有满 或者 禁忌表满了 但是移动仅仅在Q->front  到这个索引即可
             for( --j ;j >= k ; --j){
                 Q->tabuList[j+] = Q->tabuList[j];
             }/*for end*/

         }
         else{
             //禁忌表满了且 Q->front 值大于 Q->tabuIndex
             for( ;j == Q->front; --j ){
                 )
                     Q->tabuList[j] =Q->tabuList[j-];
                 else{ //j == 0
                      j = TabuLength ;
                     Q->tabuList[] = Q->tabuList[j-];
                 }
             }/*for ...end */
         }
         //惩罚策略
         Q->tabuList[Q->front] = tabu;

     }/*if find .. else ..end*/

 }

 /******************************************************************************************2Opt邻域+TSp核心算法***********************************/

 /*************************************************
 **Function: CreateMotionStruct
 **Description: 创建并初始化2-Opt 移动信息表格
 **Calls: 无
 **Called By:  Init2Opt()
 **Input: neighbor  邻居数量
 **Output: 无
 **Return: MotionTable *指针变量
 **Others: 不用这块内存的时候要释放掉 !
 *************************************************/
 MotionTable* CreateMotionStruct(int neighbor)
 {
     int i;
     MotionTable * motiontable = (MotionTable *)malloc(sizeof(MotionTable)*neighbor );
     ;i< neighbor;i++){
         motiontable->tabu.smallNum  =;
         motiontable->tabu.bigNum = ;
         motiontable->changedistance = ;
     }
     return motiontable;
 } 

 /*************************************************
 **Function: CreateSolutionSpace
 **Description: 创建并初始化解空间
 **Calls: 无
 **Called By:  Init2Opt()
 **Input: cityNum  城市数量
 **Output: 无
 **Return: StrSolve  *指针变量
 **Others: 不用这块内存的时候要逐一释放掉 !
 *************************************************/
 StrSolve *CreateSolutionSpace(int cityNum)
 {
     int i;
     StrSolve *strSolve = (StrSolve *)malloc( sizeof(StrSolve) ) ;
     strSolve->initSolution = ( ElementType *)malloc(sizeof(ElementType)*cityNum );
     strSolve->currentSolution = ( ElementType *)malloc(sizeof(ElementType)*cityNum );
     strSolve->optimalSolution = ( ElementType *)malloc(sizeof(ElementType)*cityNum );
     strSolve->tempSolution = ( ElementType *)malloc(sizeof(ElementType)*cityNum );

     //初始化解空间
     ;i< cityNum;i++){
         strSolve->initSolution[i] = (ElementType);
         strSolve->currentSolution[i] = (ElementType);
         strSolve->optimalSolution[i] = (ElementType);
         strSolve->tempSolution[i] = (ElementType);
     }
     strSolve->lastdistance  = ;//记录上次迭代获得最好的距离值
     return strSolve;
  } 

 /*************************************************
 **Function: GetInitSolution
 **Description: 获得初始解
 **Calls: 无
 **Called By:  Init2Opt()
 **Input: StrSolve * 指针变量
 **Output: 无
 **Return: StrSolve  *指针变量
 **Others: 这里在初始化解的时候可以用其他元启发式算法得出一个较好的解  !
 @brief :思路 可以用一个记录初始解的类数组(申请的内存 大小为初始解的元素个数),之后循环 CityNum-1次,不断的产生1-CityNum-1的随机数
  没产生一个就记录这个值 之后再次产生与上次不同的随机数 ,依次这样循环即可  不过速度上会很慢
 *************************************************/
 void GetInitSolution(StrSolve * strSolve)
 {
     int i;

     //默认从0号城市顺序开始 这里的0是固定不动的
     ;i<CityNum;i++){
         strSolve->initSolution[i] = i;
         strSolve->currentSolution[i] = i;
         strSolve->optimalSolution[i] = i;
         strSolve->tempSolution[i] = i;
     }

 }

 /*************************************************
 **Function: Init2Opt
 **Description: 初始化TSP需要用的值
 **Calls: CreateMotionStruct()  CreateSolutionSpace()  GetInitSolution()
 **Called By:  main()
 **Input: 无
 **Output: 无
 **Return: void
 **Others: 这里在初始化解的时候可以用其他元启发式算法得出一个较好的解  ! 不知道为什么只能在Main函数中调用否则 会出现段错误
 *************************************************/
 void Init2Opt()
 {
     motionTable = CreateMotionStruct(Neighbor);//初始化变化表  记录变化邻居值
     SolutionSpace = CreateSolutionSpace(CityNum);//创建解空间
     GetInitSolution(SolutionSpace);//初始化解
 }

 /*************************************************
 **Function: MemFree
 **Description: 释放申请的动态内存
 **Calls:
 **Called By:  main()
 **Input: distance 存储城市距离的变量指针  queue 禁忌表队列  motiontable 移动表的指针  strSolve  解空间的指针
 **Output: 无
 **Return: void
 **Others: 这里也可以一步一步的释放掉 各自的指针 因为就用一个.c所以释放内存的操作都在这里进行
 *************************************************/
 void MemFree(ElementType ** distance,Queue *queue,MotionTable *motiontable,StrSolve *strSolve)
 {
     ;
     ;

     //释放矩阵元素存储区
     ;i < CityNum; i++){
         free( distance[i] );
     }
     free(distance);

     //释放移动表
     free(motiontable); 

     //释放掉队列区
     free(queue->tabuList);
     free(queue);

     //释放解空间
     free(strSolve->initSolution);
     free(strSolve->currentSolution);
     free(strSolve->optimalSolution);
     free(strSolve->tempSolution);
     free(strSolve); 

 }

 /*************************************************
 **Function: FindPosition
 **Description: 在数组中找到指定元素值的位置
 **Calls:
 **Called By:  Get2OptChangeDistance()  TSP()
 **Input: solution 一维数组指针  tabu  Tabu结构指针
 **Output: 无
 **Return: void
 **Others: 这里是从solution[1]开始查找到的!
 *************************************************/
 static void FindPosition(const ElementType * solution,Tabu *tabu)
 {
     int i;
     Tabu tempTabu;
     ; i< CityNum;i++){
         if( solution[i] == tabu->smallNum )
             tempTabu.smallNum = i;
         if( solution[i] == tabu->bigNum )
             tempTabu.bigNum = i;
     }
     *tabu = tempTabu;//不能直接返回&tempTabu  因为这个是一个局部的变量 会有悬挂指针的后果
 }

 /*************************************************
 **Function: FindPosition
 **Description: 获得2邻域变化值
 **Calls: FindPosition()
 **Called By:  Get2optSolution()
 **Input:  tabu  Tabu结构指针  solution 一维数组指针
 **Output: 无
 **Return: ElementType 2邻域城市变化值
 **Others: 返回的值越小越好 !
 *************************************************/
 static ElementType Get2OptChangeDistance(Tabu * tabu,const ElementType * solution)
 {
     ElementType change1,change2;
     Tabu tempTabu1 = *tabu;
     Tabu tempTabu;
     change1 = change2 = ;
     FindPosition(solution,&tempTabu1); //此时这里的tempTabu1存储的就是指定元素在 解空间中的位置
     tempTabu.bigNum  = ( tempTabu1.bigNum >tempTabu1.smallNum )? tempTabu1.bigNum: tempTabu1.smallNum;
     tempTabu.smallNum  = ( tempTabu1.bigNum >tempTabu1.smallNum )? tempTabu1.smallNum: tempTabu1.bigNum;

     ){//两个元素在解空间中的 位置相差1
              ){    //最大值位置 在最后一个位置
                 change1  = Distance[ solution[tempTabu.smallNum -] ][ solution[tempTabu.smallNum] ]+\
                               Distance[ solution[tempTabu.bigNum] ][ solution[ ] ];
                 change2 =  Distance[ solution[tempTabu.smallNum -] ][ solution[tempTabu.bigNum] ] +\
                               Distance[    solution[tempTabu.smallNum] ][ solution[] ];
                 return (change2 - change1);//这个值越小越好
             }
             else{
                 change1  = Distance[ solution[tempTabu.smallNum -] ][ solution[tempTabu.smallNum] ] +\
                               Distance[ solution[tempTabu.bigNum] ][ solution[ tempTabu.bigNum +] ];
                 change2 =  Distance[ solution[tempTabu.smallNum -] ][ solution[tempTabu.bigNum] ]   +\
                               Distance[    solution[tempTabu.smallNum] ][ solution[tempTabu.bigNum +] ];

                 return (change2 - change1);
             }
     }
     else{//两个元素位置 不挨着
          ){    //最大值位置 在最后一个位置
                 change1 = Distance[ solution[tempTabu.smallNum -] ][ solution[tempTabu.smallNum] ] +\
                              Distance[ solution[tempTabu.smallNum] ][ solution[tempTabu.smallNum +] ] +\
                              Distance[ solution[tempTabu.bigNum-] ][ solution[ tempTabu.bigNum ] ]    +\
                              Distance[ solution[tempTabu.bigNum] ][ solution[ ] ];
                 change2 = Distance[ solution[tempTabu.smallNum -] ][ solution[tempTabu.bigNum] ] +\
                              Distance[ solution[tempTabu.bigNum] ][ solution[tempTabu.smallNum+] ]    +\
                              Distance[ solution[tempTabu.bigNum-] ][ solution[ tempTabu.smallNum ] ]+\
                              Distance[ solution[tempTabu.smallNum] ][ solution[] ];
                 return (change2 - change1);//这个值越小越好
             }
             else{

                 change1 = Distance[ solution[tempTabu.smallNum -] ][ solution[tempTabu.smallNum] ] +\
                              Distance[ solution[tempTabu.smallNum] ][ solution[tempTabu.smallNum +] ] +\
                              Distance[ solution[tempTabu.bigNum-] ][ solution[ tempTabu.bigNum ] ]    +\
                              Distance[ solution[tempTabu.bigNum] ][ solution[ tempTabu.bigNum +] ];
                 change2 = Distance[ solution[tempTabu.smallNum -] ][ solution[tempTabu.bigNum] ] +\
                              Distance[ solution[tempTabu.bigNum] ][ solution[tempTabu.smallNum+] ]    +\
                              Distance[ solution[tempTabu.bigNum-] ][ solution[ tempTabu.smallNum ] ]+\
                              Distance[ solution[tempTabu.smallNum] ][ solution[tempTabu.bigNum +] ];
                 return (change2 - change1);
             }
     }

 }

 /*************************************************
 **Function: Get2optSolution
 **Description: 得到1个2邻域解 将移动元素,及其导致路径的变化值 存储到移动表中
 **Calls: Get2OptChangeDistance()
 **Called By:  TSP()
 **Input:  strSolve 解空间指针  motiontable 移动表指针
 **Output: 无
 **Return: void
 **Others: 随机数要注意!
 *************************************************/
 void Get2optSolution(const StrSolve * strSolve,MotionTable *motiontable )
 {
     //产生一个1-CityNum-1之间的随机数  因为默认0为初始位置 不能动
     ElementType temp;
     ElementType changeDistance;
     int rand1,rand2;

 //    rand1 = (CityNum-1) *rand()/(RAND_MAX + 1.0);
     rand1 = rand()%(CityNum-)+;
     rand2 = rand()%(CityNum-)+;
     while(  rand2 == rand1 )//必须产生两个不同的随机数 切不能为0
         rand2 = rand()%(CityNum-) +; 

     //记录交换的两个元素 (不是位置)
     motiontable->tabu.smallNum  = (rand2 >rand1)? rand1:rand2;
     motiontable->tabu.bigNum =     (rand2 >rand1)? rand2:rand1;
     motiontable->changedistance = Get2OptChangeDistance( &motiontable->tabu ,strSolve->tempSolution ); 

 }

 /*************************************************
 **Function: Insert_Sort
 **Description: 按从小到大排序 插入排序 将制定的类数组变量 的内容进行排序
 **Calls: 无
 **Called By:  FindBestMotionValue()
 **Input:    motiontable 移动表指针  n为类数组 元素个数
 **Output: 无
 **Return: void
 **Others:
 *************************************************/
 void Insert_Sort (MotionTable * motiontable,int n)
 {
     //进行N-1轮插入过程
     int i,k;
     ; i<n; i++){
      //首先找到元素a[i]需要插入的位置

          ;
          while( (motiontable[j].changedistance < motiontable[i].changedistance )  && (j <i ) )
                  j++;

          //将元素插入到正确的位置
          if(i != j){  //如果i==j,说明a[i]刚好在正确的位置
              MotionTable temp = motiontable[i];
              for(k = i; k > j; k--){
                  motiontable[k] = motiontable[k-];
              }
              motiontable[j] = temp;
          }
     }
 }

 /*************************************************
 **Function: FindBestMotionValue
 **Description: 找到移动表中最小的值 即为最优值
 **Calls: Insert_Sort()
 **Called By:  TSP()
 **Input:    motiontable 移动表指针
 **Output: 无
 **Return: MotionTable *型的指针 存储移动表中最好值的表格指针
 **Others:
 *************************************************/
 MotionTable * FindBestMotionValue( MotionTable * motiontable)
 {
     //下面是仅仅找到一个最好的值 不管在不在禁忌表中
 //    MotionTable *bestMotion= motiontable;
 //    MotionTable *start = motiontable;
 //    MotionTable *end     = motiontable + Neighbor-1;
 //    while(start++ < end ){
 //        if( start->changedistance < bestMotion->changedistance){
 //            bestMotion = start;//保存最好的结构
 //        }
 //    }
 //    if( start->changedistance < bestMotion->changedistance )
 //        bestMotion = start;
 //    return bestMotion;//f返回最好结构的指针
     Insert_Sort(motiontable,Neighbor);//选择排序算法 从小到大排    

     return motiontable;//返回最好元素的地址
 } 

 /*************************************************
 **Function: GetInitLevel
 **Description: 获取初始解的渴望水平
 **Calls:
 **Called By:  TSP()
 **Input:    distance 存储城市的矩阵指针 initSolution 初始解指针
 **Output: 无
 **Return: 初始解的渴望水平
 **Others:
 *************************************************/
 int GetInitLevel( ElementType **distance,ElementType * initSolution)
 {
     int i;
     ;
     ; i < CityNum- ; i++){
         SumLevel += distance[ initSolution[i] ][ initSolution[i+] ];
     }
     SumLevel+= distance[ initSolution[i] ][];//最后在加上 最后一个值和初始值的 距离 才是循环的总距离距离 

     return SumLevel;
 }

 /*************************************************
 **Function: TSP
 **Description: TSP核心算法
 **Calls: GetInitLevel()
 **Called By:  TSP()  Get2optSolution()  FindBestMotionValue()  UpdateTabu()  FindPosition()  memcpy()
 **Input:    distance 存储城市的矩阵指针 solutionSpace 解空间指针 motiontable 移动表 desireLevel 渴望水平 queue 禁忌表队列指针
 **Output: 最优解信息
 **Return: void
 **Others:
 *************************************************/
 void TSP(  ElementType **distance, StrSolve * solutionSpace ,MotionTable *motiontable,int *desireLevel,Queue *queue)
 {
     int i;
     int temp;
     ;
     MotionTable * BestMotionStruct;
     ElementType BestChangeDistance;//最好的改变的值
 //    Init2Opt();//初始化相关
     *desireLevel = GetInitLevel(distance,solutionSpace->initSolution);
     solutionSpace->lastdistance = *desireLevel;//初始最优值为上次移动的最好的距离
     solutionSpace->initdistance = solutionSpace->lastdistance;//将初始值给初始距离  之后再判断 减少的距离
     printf("初始距离:%d ",*desireLevel);
 //    printf("初始最好的距离是%d,solutionSpace->lastdistance = %d\n",*desireLevel,solutionSpace->lastdistance);
     printf("城市数量:%d 迭代次数:%d 邻居个数:%d\n",CityNum,MaxNG,Neighbor);
     //迭代 次数作为停止条件
     while( currentNG++ < MaxNG ){
         //获得邻居最好解
         ; neighborNum < Neighbor; neighborNum++ ){//循环Neighbor那么多次
             Get2optSolution(SolutionSpace,&motionTable[neighborNum] );//将邻域 移动放在移动表中
         } 

         //找到移动表中最小的值 此时解若是 < 渴望水平 则更新最优解 否则找到不在禁忌表中的 最好的解 更新当前解
         BestMotionStruct = FindBestMotionValue( motiontable);
         BestChangeDistance = BestMotionStruct->changedistance;

          if( solutionSpace->lastdistance + BestChangeDistance < *desireLevel){//当前迭代出的最好的解 小于渴望水平 更新最优解T表当前解
             int temp;
             //更新T表
             UpdateTabu(queue,&BestMotionStruct->tabu);
             //更新渴望水平
             *desireLevel = solutionSpace->lastdistance +BestChangeDistance;
             //更新上次迭代的最优值
             solutionSpace->lastdistance = *desireLevel;
             //更新当前解和最优解
             FindPosition(solutionSpace->tempSolution,&BestMotionStruct->tabu);//找到当前解 对应的解空间的位置
             temp = solutionSpace->tempSolution[ BestMotionStruct->tabu.smallNum ];
             solutionSpace->tempSolution[ BestMotionStruct->tabu.smallNum] = solutionSpace->tempSolution[ BestMotionStruct->tabu.bigNum ];
             solutionSpace->tempSolution[ BestMotionStruct->tabu.bigNum ] = temp;
             memcpy( solutionSpace->currentSolution,solutionSpace->tempSolution,sizeof(ElementType)*CityNum ); //将临时解空间值复制到当前解空间
             memcpy( solutionSpace->optimalSolution,solutionSpace->tempSolution,sizeof(ElementType)*CityNum );

         }
         else{//没有小于渴望水平 找到不在禁忌表中最好的移动
             //在移动表中找到不在禁忌表中最好元素 因为拍好序了 所以从表的第二个值开始找即可
             int i;
             ;i< Neighbor; i++){
                 if( !IsFindTabu(queue,&motiontable[i].tabu) ){
                     int temp;
                     //不在禁忌表中  则这个值就是目前来说最好的值
                     BestMotionStruct = &motiontable[i];
                     //更新T表
                     UpdateTabu(queue,&BestMotionStruct->tabu);
                     solutionSpace->lastdistance = solutionSpace->lastdistance + BestMotionStruct->changedistance;
                     //更新当前解
                     FindPosition(solutionSpace->tempSolution,&BestMotionStruct->tabu);//找到当前解 对应的解空间的位置
                     temp = solutionSpace->tempSolution[ BestMotionStruct->tabu.smallNum ];
                     solutionSpace->tempSolution[ BestMotionStruct->tabu.smallNum] = solutionSpace->tempSolution[ BestMotionStruct->tabu.bigNum ];
                     solutionSpace->tempSolution[ BestMotionStruct->tabu.bigNum ] = temp;
                     memcpy( solutionSpace->currentSolution,solutionSpace->tempSolution,sizeof(ElementType)*CityNum ); //将临时解空间值复制到当前解空间 

                     break;//跳出循环
                 }
             }
         }

     }
     currentNG = ;//将全局迭代次数变量值清零
     printf("\n初始值:%d 最优解值:%d 优化距离:%d\n最优解元素:\n\n",\
         solutionSpace->initdistance,\
         GetInitLevel(distance,solutionSpace->optimalSolution),solutionSpace->initdistance - *desireLevel);
      ;i< CityNum;i++){
         printf("%d-> ",solutionSpace->optimalSolution[i]);
     }
     printf( ] );
 } 

原创:TSP问题解决方案-----禁忌搜索算法C实现的更多相关文章

  1. 禁忌搜索算法TSA 旅行商问题TSP python

    import math import random import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot ...

  2. 【算法】禁忌搜索算法(Tabu Search,TS)超详细通俗解析附C++代码实例

    01 什么是禁忌搜索算法? 1.1 先从爬山算法说起 爬山算法从当前的节点开始,和周围的邻居节点的值进行比较. 如果当前节点是最大的,那么返回当前节点,作为最大值 (既山峰最高点):反之就用最高的邻居 ...

  3. 【高级算法】禁忌搜索算法解决3SAT问题(C++实现)

    转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46440389 近期梳理,翻出了当年高级算法课程做的题目.禁忌搜索算法解决3SAT问 ...

  4. 原创:工作指派问题解决方案---模拟退火算法C实现

    本文忽略了对于模拟退火的算法的理论讲解,读者可参考相关的博文或者其他相关资料,本文着重于算法的实现: /************************************************ ...

  5. 【原创】BI解决方案选型之ETL数据整合工具对比

    一.背景 在企业BI平台建设过程中,数据整合始终是一切的基础,简单BI项目可以通过存储过程来实现,而复杂.全面.多方异构数据来源等就大大增加了复杂性,存储过程的可管理性.可维护性.容错性等就无法很好的 ...

  6. 【智能算法】变邻域搜索算法(Variable Neighborhood Search,VNS)超详细解析和TSP代码实例以及01背包代码实例

    喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 00 目录 局部搜索再次科普 变邻域搜索 造轮子写代码 01 局部搜索科普三连 虽然之前做的很多篇启发式的算法都有跟大家提过局部 ...

  7. 智能优化算法对TSP问题的求解研究

    要求: TSP 算法(Traveling Salesman Problem)是指给定 n 个城市和各个城市之间的距离,要 求确定一条经过各个城市当且仅当一次的最短路径,它是一种典型的优化组合问题,其最 ...

  8. 模拟退火算法SA原理及python、java、php、c++语言代码实现TSP旅行商问题,智能优化算法,随机寻优算法,全局最短路径

    模拟退火算法SA原理及python.java.php.c++语言代码实现TSP旅行商问题,智能优化算法,随机寻优算法,全局最短路径 模拟退火算法(Simulated Annealing,SA)最早的思 ...

  9. 【算法】变邻域搜索算法(Variable Neighborhood Search,VNS)超详细一看就懂的解析

    更多精彩尽在微信公众号[程序猿声] 变邻域搜索算法(Variable Neighborhood Search,VNS)一看就懂的解析 00 目录 局部搜索再次科普 变邻域搜索 造轮子写代码 01 局部 ...

随机推荐

  1. 阿里 java学习之路

    https://maimai.cn/article/detail?fid=96107193&push_id=5603&share_user=http%3A%2F%2Fi9.taou.c ...

  2. spi master接口的fpga实现

    前言 当你器件的引脚贼少的时候,需要主机和从机通信,spi就派上了用场,它可以一对多,但只是片选到的从机能和主机通信,其他的挂机. spi:serial peripheral interface 串行 ...

  3. Bootstrap-table事件使用

    HTML <div class="alert alert-danger" id="eventInfo"></div> <table ...

  4. 在centos6上实现编译安装lamp和wordpress,并编译xcache

    author:JevonWei 版权声明:原创作品 软件环境: centos6.9 httpd-2.4.27.tar.bz2 apr-1.5.2.tar.bz2 apr-util-1.5.4.tar. ...

  5. maven 自我学习笔记

    1.常用网站: maven.apache.org http://mvnrepository.com/   2.命令 mvn -v 查看maven的版本 mvn -compile 在项目的根目录下编译项 ...

  6. poj 1882完全背包变形

    题意:给出一个上限硬币数量s,给出n套硬币价值,求一套硬币能用不大于s数量的硬币组成从1开始连续的区间价值,其中,如果其最大值相同,输出数量小的和价值小的. 思路:很明显的完全背包,纠结后面最大值相同 ...

  7. poj 1948二维01背包

    题意:给出不多于40个小棍的长度,求出用所有小棍组成的三角形的最大面积. 思路:三角形3边求面积,海伦公式:p=(a+b+c)/2;S=p*(p-a)*(p-b)*(p-c);因为最大周长为1600  ...

  8. js page click

     DataTables  Editor Your account: Login / Register Examples Manual Reference Options API Events Butt ...

  9. js 实现 input type="file" 文件上传示例代码

    在开发中,文件上传必不可少但是它长得又丑.浏览的字样不能换,一般会让其隐藏点其他的标签(图片等)来时实现选择文件上传功能 在开发中,文件上传必不可少,<input type="file ...

  10. Linux下undefined reference to ‘pthread_create’问题解决

    Linux下undefined reference to 'pthread_create'问题解决 在试用Linux 线程模块时,试用pthread_create 函数. 编译命令为 gcc main ...