当前位置:   article > 正文

西工大数据结构实验NOJ参考代码和分析合集_西工大noj

西工大noj

实验1.1 合并有序数组

  1. //001合并有序数组
  2. #include <bits/stdc++.h>
  3. #define MAXSIZE 20 //数组的最大长度为20
  4. typedef struct //定义线性表的顺序存储结构
  5. {
  6. int elem[MAXSIZE];
  7. int last = -1;
  8. } SeqList;
  9. void inputList(SeqList *la, SeqList *lb) //输入两个线性表
  10. {
  11. int n, m;
  12. scanf("%d", &n);
  13. for (int i = 0; i < n; i++)
  14. {
  15. scanf("%d", &la->elem[i]);
  16. la->last++;
  17. }
  18. scanf("%d", &m);
  19. for (int i = 0; i < m; i++)
  20. {
  21. scanf("%d", &lb->elem[i]);
  22. lb->last++;
  23. }
  24. }
  25. void mergeList(SeqList *la, SeqList *lb, SeqList *lc) //合并数组
  26. {
  27. int ia, ib, ic; //三个数分别指向三个线性表中正在进行数据处理的位置
  28. ia = 0;
  29. ib = 0;
  30. ic = 0; //从头开始处理
  31. while (ia <= la->last && ib <= lb->last) //两个数组都没有处理完数据时
  32. {
  33. if (la->elem[ia] <= lb->elem[ib]) //比较当前的两个数,将较小数放入lc中
  34. {
  35. lc->elem[ic] = la->elem[ia];
  36. ia++;
  37. ic++;
  38. }
  39. else
  40. {
  41. lc->elem[ic] = lb->elem[ib];
  42. ib++;
  43. ic++;
  44. }
  45. }
  46. while (ia <= la->last) //当有一个或两个数组完成了对所有数据的处理,则将没有完成数据处理的数组中剩余的元素依次放入lc中
  47. {
  48. lc->elem[ic] = la->elem[ia];
  49. ia++;
  50. ic++;
  51. }
  52. while (ib <= lb->last)
  53. {
  54. lc->elem[ic] = lb->elem[ib];
  55. ib++;
  56. ic++;
  57. }
  58. lc->last = la->last + lb->last + 1;
  59. }
  60. void printList(int length, SeqList *L) //打印线性表
  61. {
  62. for (int i = 0; i < length; i++)
  63. printf("%d\n", L->elem[i]);
  64. }
  65. int main()
  66. {
  67. SeqList la, lb, lc;
  68. inputList(&la, &lb);
  69. mergeList(&la, &lb, &lc);
  70. printList(la.last + lb.last + 2, &lc);
  71. return 0;
  72. }

实验1.2 高精度计算PI值

  1. //002高精度计算PI值
  2. #include <bits/stdc++.h>
  3. typedef struct list //定义双向链表
  4. {
  5. int data;
  6. struct list *next;
  7. struct list *prior;
  8. } list;
  9. list *Initlist() //初始化双向链表
  10. {
  11. list *head;
  12. head = (list *)malloc(sizeof(list));
  13. head->next = head->prior = head;
  14. return head;
  15. }
  16. list *Creatlist(list *head) //建立链表
  17. {
  18. int i;
  19. list *p;
  20. p = head;
  21. for (i = 0; i < 1000; i++)
  22. {
  23. list *q = (list *)malloc(sizeof(list));
  24. q->data = 0;
  25. q->prior = p;
  26. p->next = q;
  27. q->next = head; //第一次循环时此时的head和p是一个东西,目的为把链表画成一个圈
  28. head->prior = q;
  29. p = p->next;
  30. }
  31. return head;
  32. }
  33. int main()
  34. {
  35. int n, i, a, b;
  36. scanf("%d", &n);
  37. list *number, *sum;
  38. list *p, *q, *x;
  39. number = Initlist();
  40. sum = Initlist();
  41. number = Creatlist(number);
  42. sum = Creatlist(sum);
  43. number->next->data = 2; //第一位储存2,即2*R(1)=2
  44. sum->next->data = 2; //与上同理
  45. a = 0, b = 0; //分别是用来暂时存储进位和余数
  46. for (i = 1; i < 2500; i++) //循环两千次,确保精确度
  47. {
  48. p = number->prior; //做大数乘法时从链表的后方开始
  49. while (p != number) //大于10则把10位的数字给b,个位数字放入data域中。
  50. {
  51. a = p->data * i + b;
  52. p->data = a % 10;
  53. b = a / 10;
  54. p = p->prior;
  55. }
  56. b = 0; //清空b,为除法做准备
  57. p = p->next; //大数除法从链表的前方开始
  58. while (p != number) //若计算出的数字为自然数,则直接放入data域;若等于0,或为小数,则要计算余数并给b。
  59. {
  60. a = p->data + b * 10;
  61. p->data = a / (2 * i + 1);
  62. b = a % (2 * i + 1);
  63. p = p->next;
  64. }
  65. b = 0; //清零
  66. p = number->prior; //大数加法均从末尾开始
  67. q = sum->prior;
  68. while (p != number) //大于10进位,并储存个位数,进位数字赋给b。
  69. {
  70. a = p->data + q->data + b;
  71. q->data = a % 10;
  72. b = a / 10;
  73. p = p->prior;
  74. q = q->prior;
  75. }
  76. }
  77. printf("3.");
  78. x = sum->next->next; //从小数开始输出。
  79. for (i = 0; i < n; i++)
  80. {
  81. printf("%d", x->data);
  82. x = x->next;
  83. }
  84. return 0;
  85. }

实验2.1 稀疏矩阵转置

  1. //003稀疏矩阵转置:一次定位快速转置法
  2. #include <bits/stdc++.h>
  3. #define MAXSIZE 2000
  4. typedef struct triple
  5. { //定义三元组
  6. int r, c, e; //三元组的坐标和元素值
  7. } triple;
  8. typedef struct matrix
  9. { //定义稀疏矩阵
  10. int m, n, t; //稀疏矩阵的行列数和非零元素个数
  11. triple data[MAXSIZE]; //该稀疏矩阵中的三元组信息 从下标1开始
  12. } matrix;
  13. void initMatrixA(matrix *M) //初始化矩阵A
  14. {
  15. scanf("%d%d", &M->m, &M->n); //输入矩阵信息
  16. M->t = 0;
  17. int temp_r, temp_c, temp_e;
  18. while (true) //输入三元组信息
  19. {
  20. scanf("%d", &temp_r);
  21. getchar();
  22. scanf("%d", &temp_c);
  23. getchar();
  24. scanf("%d", &temp_e);
  25. getchar();
  26. if (temp_r == 0 && temp_c == 0 && temp_e == 0)
  27. {
  28. break;
  29. }
  30. M->t++;
  31. M->data[M->t].r = temp_r;
  32. M->data[M->t].c = temp_c;
  33. M->data[M->t].e = temp_e;
  34. }
  35. }
  36. void initMatrixB(matrix *M, int m, int n, int t) //初始化B矩阵
  37. {
  38. M->m = n;
  39. M->n = m;
  40. M->t = t;
  41. }
  42. void transposeMatrix(matrix A, matrix *B) //转置函数
  43. {
  44. int num[MAXSIZE], pos[MAXSIZE]; //num存储A中每一列非零元素个数,pos记录不同列号对应的开始位置
  45. for (int col = 0; col < A.n; col++)
  46. {
  47. num[col] = 0;
  48. }
  49. for (int t = 1; t <= A.t; t++) //统计每一个列号对应的三元组个数
  50. {
  51. num[A.data[t].c]++;
  52. }
  53. pos[0] = 1;
  54. for (int col = 1; col < A.n; col++) //计算不同列号对应的开始位置
  55. {
  56. pos[col] = pos[col - 1] + num[col - 1];
  57. }
  58. for (int p = 1; p <= A.t; p++) //完成转置
  59. {
  60. int col = A.data[p].c;
  61. int q = pos[col];
  62. B->data[q].r = A.data[p].c;
  63. B->data[q].c = A.data[p].r;
  64. B->data[q].e = A.data[p].e;
  65. pos[col]++;
  66. }
  67. }
  68. void printResult(matrix M) //输出矩阵三元组
  69. {
  70. for (int i = 1; i <= M.t; i++)
  71. {
  72. printf("%d %d %d\n", M.data[i].r, M.data[i].c, M.data[i].e);
  73. }
  74. }
  75. int main()
  76. {
  77. matrix A, B; //定义待转置矩阵A和输出矩阵B
  78. initMatrixA(&A);
  79. initMatrixB(&B, A.m, A.n, A.t);
  80. transposeMatrix(A, &B);
  81. printResult(B);
  82. return 0;
  83. }

实验2.2 稀疏矩阵加法,实现C=A+B

  1. //004 稀疏矩阵加法
  2. #include <bits/stdc++.h>
  3. #define MAXSIZE 20000
  4. using namespace std;
  5. typedef struct triple
  6. {
  7. int x, y; //非零元素的坐标
  8. int e; //非零元素的值
  9. } triple;
  10. typedef struct matrix
  11. {
  12. int row, col, t; //定义矩阵的长宽和非零元素个数
  13. triple data[MAXSIZE]; //存储矩阵的三元组
  14. } matrix;
  15. void inputTriple(matrix *A, matrix *B) //输入矩阵三元组
  16. {
  17. for (int i = 0; i < A->t; i++)
  18. {
  19. scanf("%d%d%d", &A->data[i].x, &A->data[i].y, &A->data[i].e);
  20. }
  21. for (int i = 0; i < B->t; i++)
  22. {
  23. scanf("%d%d%d", &B->data[i].x, &B->data[i].y, &B->data[i].e);
  24. }
  25. }
  26. void addMatrix(matrix *A, matrix *B) //矩阵相加
  27. {
  28. for (int i = 0; i < B->t; i++)
  29. {
  30. for (int j = 0; j < A->t; j++)
  31. {
  32. if (A->data[j].x == B->data[i].x && A->data[j].y == B->data[i].y) //相同位置有非零元素
  33. {
  34. A->data[j].e += B->data[i].e;
  35. B->data[i].x = -1; //标记已经用过的三元组
  36. }
  37. if (A->data[j].e == 0) //排除相加后为0的三元组
  38. {
  39. A->data[j].x = -1;
  40. }
  41. }
  42. }
  43. for (int i = 0; i < B->t; i++) //对于B中没有用过的三元组进行遍历
  44. {
  45. if (B->data[i].x == -1)
  46. continue;
  47. A->data[A->t].x = B->data[i].x;
  48. A->data[A->t].y = B->data[i].y;
  49. A->data[A->t].e = B->data[i].e; //新建A的三元组
  50. A->t++;
  51. }
  52. }
  53. void sortTriple(matrix *A) //对A中三元组按照行递增和行内列递增的顺序进行排列
  54. {
  55. for (int i = 0; i < A->t; i++) //行列递增排序
  56. {
  57. for (int j = 0; j < A->t - i - 1; j++)
  58. {
  59. if (A->data[j].x > A->data[j + 1].x || (A->data[j].x == A->data[j + 1].x && A->data[j].y > A->data[j + 1].y))
  60. {
  61. triple t = A->data[j];
  62. A->data[j] = A->data[j + 1];
  63. A->data[j + 1] = t;
  64. }
  65. }
  66. }
  67. }
  68. void printMatrix(matrix A)
  69. {
  70. for (int i = 0; i < A.t; i++)
  71. {
  72. if (A.data[i].x == -1)
  73. continue;
  74. printf("%d %d %d\n", A.data[i].x, A.data[i].y, A.data[i].e);
  75. }
  76. }
  77. int main()
  78. {
  79. matrix A, B;
  80. scanf("%d%d%d%d", &A.row, &A.col, &A.t, &B.t);
  81. B.row = A.row;
  82. B.col = A.col;
  83. inputTriple(&A, &B);
  84. addMatrix(&A, &B);
  85. sortTriple(&A);
  86. printMatrix(A);
  87. return 0;
  88. }

实验2.3 稀疏矩阵加法,用十字链表实现C=A+B

  1. //005 以十字链表为存储结构实现矩阵相加
  2. #include <bits/stdc++.h>
  3. typedef struct Node
  4. {
  5. int x, y, e;
  6. Node *right, *down;
  7. } Node;
  8. typedef struct Matrix
  9. {
  10. Node **rhead, **chead;
  11. int m, n, t;
  12. } Matrix;
  13. void initMatrix(Matrix *A, Matrix *B)
  14. {
  15. scanf("%d%d%d%d", &A->m, &A->n, &A->t, &B->t);
  16. B->m = A->m;
  17. B->n = A->n;
  18. }
  19. void insertNode(Matrix *L, Node *P) //插入节点
  20. {
  21. Node *temp, *N;
  22. N = (Node *)malloc(sizeof(Node)); //新建待插入节点
  23. N->y = P->y;
  24. N->x = P->x;
  25. N->e = P->e; //装载节点信息
  26. //插入行指针
  27. if (L->rhead[N->x] == NULL || L->rhead[N->x]->y > N->y) //需要插在头结点的情况
  28. {
  29. N->right = L->rhead[N->x];
  30. L->rhead[N->x] = N;
  31. }
  32. else
  33. {
  34. for (temp = L->rhead[N->x]; temp->right && temp->right->y < N->y; temp = temp->right)
  35. ; //不断向右遍历找到正确插入位置
  36. N->right = temp->right;
  37. temp->right = N;
  38. }
  39. //插入列指针
  40. if (L->chead[N->y] == NULL || L->chead[N->y]->x > N->x)
  41. {
  42. N->down = L->chead[N->y];
  43. L->chead[N->y] = N;
  44. }
  45. else
  46. {
  47. for (temp = L->chead[N->y]; temp->down && temp->down->x < N->x; temp = temp->down)
  48. ;
  49. N->down = temp->down;
  50. temp->down = N;
  51. }
  52. }
  53. void createMatrix(Matrix *M)
  54. {
  55. Node *p, q;
  56. M->rhead = (Node **)malloc((M->m + 1) * sizeof(Node));
  57. M->chead = (Node **)malloc((M->n + 1) * sizeof(Node)); //创建行列指针表
  58. for (int i = 1; i <= M->m; i++) //初始化行列指针
  59. M->rhead[i] = NULL;
  60. for (int i = 1; i <= M->n; i++)
  61. M->chead[i] = NULL;
  62. for (int i = 1; i <= M->t; i++) //开辟节点并装在数据域和插入十字链表
  63. {
  64. p = (Node *)malloc(sizeof(Node));
  65. scanf("%d%d%d", &p->x, &p->y, &p->e);
  66. insertNode(M, p);
  67. }
  68. }
  69. void addMatrix(Matrix *A, Matrix *B)
  70. {
  71. Node *p, *temp1, *temp2;
  72. for (int i = 1; i <= B->m; i++) //枚举每一行的头指针
  73. {
  74. if (B->rhead[i] == NULL) //如果B矩阵的该行没有元素,直接跳过,不需要执行加法
  75. continue;
  76. else
  77. {
  78. if (A->rhead[i] == NULL) //如果B该行不空,但A空,问题转化为将B中节点插入A中
  79. {
  80. temp2 = B->rhead[i];
  81. while (temp2)
  82. {
  83. insertNode(A, temp2);
  84. temp2 = temp2->right;
  85. }
  86. }
  87. else //如果A该行和B该行都不空
  88. {
  89. for (temp2 = B->rhead[i];; temp2 = temp2->right)
  90. {
  91. for (temp1 = A->rhead[i];; temp1 = temp1->right) //对于该行某个B节点,枚举所有A节点
  92. {
  93. if (temp2->y == temp1->y) //如果两个节点位置重合,直接相加
  94. {
  95. temp1->e += temp2->e;
  96. break;
  97. }
  98. //如果位置不重合
  99. else if ((temp2->y < temp1->y) || temp1->right == NULL) //如果temp2的列已经大于temp1的列,说明temp2没有遇到相同列数的temp1
  100. { //又或者已经遍历到尽头都没有相同列数
  101. insertNode(A, temp2); //说明该列不可能存在相同位置了,直接插入
  102. break;
  103. }
  104. else if (temp2->y > temp1->y && temp2->y < temp1->right->y) //如果temp2正好介于两者之间
  105. {
  106. insertNode(A, temp2);
  107. break;
  108. }
  109. }
  110. if (temp2->right == NULL)
  111. break;
  112. }
  113. }
  114. }
  115. }
  116. }
  117. void printMatrix(Matrix *L)
  118. {
  119. int i;
  120. Node *p;
  121. for (i = 1; i <= L->m; i++)
  122. {
  123. p = L->rhead[i];
  124. while (p != NULL)
  125. {
  126. if (p->e != 0)
  127. printf("%d %d %d\n", p->x, p->y, p->e);
  128. p = p->right;
  129. }
  130. }
  131. }
  132. int main()
  133. {
  134. Matrix A, B;
  135. initMatrix(&A, &B);
  136. createMatrix(&A);
  137. createMatrix(&B);
  138. addMatrix(&A, &B);
  139. printMatrix(&A);
  140. return 0;
  141. }
  142. /*
  143. 3 4 3 2
  144. 1 1 1
  145. 1 3 1
  146. 2 2 2
  147. 1 2 1
  148. 2 2 3
  149. */

实验2.4 稀疏矩阵的乘法 

  1. //006 稀疏矩阵的乘法
  2. #include <bits/stdc++.h>
  3. #define MAXSIZE 2000
  4. typedef struct triple
  5. { //定义三元组
  6. int r, c, e; //三元组的坐标和元素值
  7. } triple;
  8. typedef struct matrix
  9. { //定义稀疏矩阵
  10. int m, n, t; //稀疏矩阵的行列数和非零元素个数
  11. triple data[MAXSIZE]; //该稀疏矩阵中的三元组信息 从下标1开始
  12. } matrix;
  13. void initMatrix(matrix *M) //初始化稀疏矩阵
  14. {
  15. scanf("%d", &M->m);
  16. getchar();
  17. scanf("%d", &M->n);
  18. while (true)
  19. {
  20. triple *p = (triple *)malloc(sizeof(triple));
  21. scanf("%d", &p->r);
  22. getchar();
  23. scanf("%d", &p->c);
  24. getchar();
  25. scanf("%d", &p->e);
  26. if (!p->c)
  27. break;
  28. M->t++;
  29. M->data[M->t].r = p->r;
  30. M->data[M->t].c = p->c;
  31. M->data[M->t].e = p->e;
  32. }
  33. }
  34. void multiplyMatrix(matrix A, matrix B, matrix *C)
  35. {
  36. int temp = 0; //temp用于累加当前行列相乘所得到的结果
  37. for (int i = 1; i <= A.m; i++)
  38. {
  39. for (int j = 1; j <= B.n; j++) //外两层循环是分别遍历第一个矩阵的行号和第二个矩阵的列号,排列组合
  40. {
  41. for (int p = 1; p <= A.t; p++)
  42. {
  43. for (int q = 1; q <= B.t; q++) //内两层循环是遍历所有元素,找到能进行乘法的元素数对
  44. {
  45. if (A.data[p].r == i && B.data[q].c == j && A.data[p].c == B.data[q].r)
  46. {
  47. temp += A.data[p].e * B.data[q].e;
  48. }
  49. }
  50. }
  51. if (!temp)
  52. continue;
  53. else
  54. {
  55. C->t++;
  56. C->data[C->t].r = i;
  57. C->data[C->t].c = j;
  58. C->data[C->t].e = temp;
  59. temp = 0;
  60. }
  61. }
  62. }
  63. }
  64. void printMatrix(matrix M) //输出矩阵三元组
  65. {
  66. for (int i = 1; i <= M.t; i++)
  67. {
  68. printf("%d %d %d\n", M.data[i].r, M.data[i].c, M.data[i].e);
  69. }
  70. }
  71. int main()
  72. {
  73. matrix A, B, C;
  74. initMatrix(&A);
  75. initMatrix(&B);
  76. C.m = A.m;
  77. C.n = B.n;
  78. multiplyMatrix(A, B, &C);
  79. printMatrix(C);
  80. return 0;
  81. }

实验3.1 哈夫曼编/译器 

  1. //007 哈夫曼编/译码器
  2. #include <bits/stdc++.h>
  3. #define N 100 //叶子结点最大数量
  4. #define M 2 * N - 1 //所有结点最大数量
  5. typedef struct HTNode //结点
  6. {
  7. int weight; //权重
  8. int parent, lchild, rchild; //双亲、左右孩子结点
  9. char data; //字符
  10. } HTNode, HT[M + 1];
  11. HT ht;
  12. typedef struct HCNode
  13. {
  14. int bit[200]; //编码
  15. int start; //该编码的末尾位置
  16. } HCNode, HC[100];
  17. HC hc;
  18. int str[1000] = {0};
  19. int len = 0;
  20. void select(int pos, int *x1, int *x2)
  21. {
  22. int min = 100000;
  23. for (int i = 1; i <= pos; i++)
  24. {
  25. if (ht[i].weight < min && ht[i].parent == 0) //注意判断该节点必须没有双亲节点
  26. {
  27. min = ht[i].weight;
  28. *x1 = i;
  29. }
  30. }
  31. min = 100000;
  32. for (int i = 1; i <= pos; i++)
  33. {
  34. if (i == *x1)
  35. continue;
  36. if (ht[i].weight < min && ht[i].parent == 0) //注意判断该节点必须没有双亲节点
  37. {
  38. min = ht[i].weight;
  39. *x2 = i;
  40. }
  41. }
  42. }
  43. void initTree(int n)
  44. {
  45. int x1, x2;
  46. for (int i = 1; i <= 2 * n - 1; i++) //对所有结点初始化
  47. {
  48. ht[i].weight = 0;
  49. ht[i].parent = 0;
  50. ht[i].lchild = 0;
  51. ht[i].rchild = 0;
  52. }
  53. for (int i = 1; i <= n; i++) //叶子结点的data域
  54. {
  55. getchar();
  56. scanf("%c", &ht[i].data);
  57. }
  58. for (int i = 1; i <= n; i++) //叶子结点的weight域
  59. {
  60. scanf("%d", &ht[i].weight);
  61. }
  62. for (int i = n; i < 2 * n - 1; i++)
  63. {
  64. select(i, &x1, &x2); //找到序号为i的结点之前的两个最小权重结点
  65. //两个最小权重结点组成一棵树,以i处的结点为根节点,直至循环结束所有结点组成一棵树
  66. ht[i + 1].weight = ht[x1].weight + ht[x2].weight;
  67. ht[x1].parent = i + 1;
  68. ht[x2].parent = i + 1;
  69. ht[i + 1].lchild = x1;
  70. ht[i + 1].rchild = x2;
  71. }
  72. }
  73. void encode(int n)
  74. {
  75. for (int i = 1; i <= n; i++)
  76. {
  77. hc[i].start = n; //编码长度最多为n
  78. int c = i; //当前叶子结点序号
  79. int p = ht[c].parent; //叶子结点双亲序号
  80. while (p)
  81. {
  82. if (ht[p].lchild == c)
  83. hc[i].bit[hc[i].start] = 0;
  84. else
  85. hc[i].bit[hc[i].start] = 1;
  86. hc[i].start--; //准备录入下一位编码
  87. c = p; //上溯
  88. p = ht[c].parent; //上溯,直到while循环结束
  89. }
  90. hc[i].start++; //while循环中,start多退了一位。
  91. }
  92. }
  93. void printCode(int n)
  94. {
  95. len = 0;
  96. char code[1000];
  97. scanf("%s", code);
  98. for (int i = 0; i < strlen(code); i++)
  99. {
  100. for (int j = 1; j <= n; j++)
  101. {
  102. if (code[i] == ht[j].data)
  103. {
  104. for (int k = hc[j].start; k <= n; k++)
  105. {
  106. printf("%d", hc[j].bit[k]);
  107. str[len] = hc[j].bit[k]; //存储待破解编码
  108. len++;
  109. }
  110. }
  111. }
  112. }
  113. printf("\n");
  114. }
  115. void decode(int n) //译码并输出
  116. {
  117. int t;
  118. for (int i = 0; i < len;)
  119. {
  120. t = 2 * n - 1; //根节点
  121. while (ht[t].lchild != 0 && ht[t].rchild != 0) //当找到叶子节点时,退出循环
  122. {
  123. if (str[i] == 0)
  124. t = ht[t].lchild;
  125. else
  126. t = ht[t].rchild;
  127. i++;
  128. }
  129. printf("%c", ht[t].data);
  130. }
  131. }
  132. int main()
  133. {
  134. int n;
  135. scanf("%d", &n);
  136. initTree(n);
  137. encode(n);
  138. printCode(n);
  139. decode(n);
  140. return 0;
  141. }

实验4.1 求赋权图中一个结点到所有结点的最短路径的长度 

  1. //求赋权图中一个结点到所有结点的最短路径长度
  2. #include <bits/stdc++.h>
  3. #define MAXSIZE 105
  4. #define INF 10000
  5. int ans[MAXSIZE] = {0};
  6. typedef struct Graph
  7. {
  8. int data[MAXSIZE];
  9. int arc[MAXSIZE][MAXSIZE];
  10. int Vnum, Anum;
  11. } Graph;
  12. typedef struct dijkstra
  13. {
  14. bool visited[MAXSIZE];
  15. int length[MAXSIZE];
  16. } Dij;
  17. void initGraph(Graph *G)
  18. {
  19. scanf("%d", &G->Vnum);
  20. for (int i = 0; i < G->Vnum; i++)
  21. {
  22. for (int j = 0; j < G->Vnum; j++)
  23. {
  24. scanf("%d", &G->arc[i][j]);
  25. }
  26. }
  27. }
  28. void initDij(Graph *G, Dij *D)
  29. {
  30. for (int i = 0; i < G->Vnum; i++)
  31. {
  32. D->visited[i] = 0;
  33. D->length[i] = INF;
  34. }
  35. D->visited[0] = 1;
  36. D->length[0] = 0;
  37. for (int i = 0; i < G->Vnum; i++)
  38. {
  39. if (G->arc[0][i] != 10000)
  40. {
  41. D->length[i] = G->arc[0][i];
  42. }
  43. }
  44. }
  45. int searchMinLengthV(Graph *G, Dij *D)
  46. {
  47. int min = 10000;
  48. int r;
  49. for (int i = 0; i < G->Vnum; i++)
  50. {
  51. if (!D->visited[i] && D->length[i] < min)
  52. {
  53. min = D->length[i];
  54. r = i;
  55. }
  56. }
  57. D->visited[r] = true;
  58. return r;
  59. }
  60. bool judgeFinished(Graph *G, Dij *D)
  61. {
  62. for (int i = 0; i < G->Vnum; i++)
  63. {
  64. if (!D->visited[i])
  65. return false;
  66. }
  67. return true;
  68. }
  69. int min(int a, int b)
  70. {
  71. return a > b ? b : a;
  72. }
  73. void updateArcV(int V0, Graph *G, Dij *D)
  74. {
  75. for (int i = 0; i < G->Vnum; i++)
  76. {
  77. if (G->arc[V0][i] != 10000 && !D->visited[i])
  78. {
  79. D->length[i] = min(D->length[i], D->length[V0] + G->arc[V0][i]);
  80. }
  81. }
  82. }
  83. void findMinPath(Graph *G, Dij *D)
  84. {
  85. initDij(G, D);
  86. for (int i = 0; i < G->Vnum - 1; i++)
  87. {
  88. int t = searchMinLengthV(G, D);
  89. if (judgeFinished(G, D))
  90. return;
  91. updateArcV(t, G, D);
  92. }
  93. }
  94. void printPath(Graph *G, Dij *D)
  95. {
  96. for (int i = 0; i < G->Vnum; i++)
  97. {
  98. printf("%d\n", D->length[i]);
  99. }
  100. }
  101. int main()
  102. {
  103. Graph G;
  104. Dij D;
  105. initGraph(&G);
  106. int ans[MAXSIZE] = {0};
  107. findMinPath(&G, &D);
  108. printPath(&G, &D);
  109. return 0;
  110. }
  111. /*
  112. 6
  113. 0 1 4 10000 10000 10000
  114. 1 0 2 7 5 10000
  115. 4 2 0 10000 1 10000
  116. 10000 7 10000 0 3 2
  117. 10000 5 1 3 0 6
  118. 10000 10000 10000 2 6 0
  119. */

实验4.2 用迪杰斯特拉算法求赋权图中的最短路径 

  1. /*实验4.2:用迪杰斯特拉算法求赋权图中的最短路径
  2. 核心:
  3. 1.与上一题一样更新完成最短路径图
  4. 2.从目标结点向前寻找最短路径:按照结点的length递减的顺序;验证length-边长?=上一个结点length
  5. */
  6. #include <bits/stdc++.h>
  7. using namespace std;
  8. #define MAXSIZE 105
  9. typedef struct Graph
  10. {
  11. int Vnum;
  12. int arc[MAXSIZE][MAXSIZE];
  13. } Graph;
  14. typedef struct Dij
  15. {
  16. bool visited[MAXSIZE];
  17. int length[MAXSIZE];
  18. } Dij;
  19. typedef struct Stack
  20. {
  21. int top;
  22. int data[MAXSIZE];
  23. } Stack;
  24. void push_stack(Stack *S, int e)
  25. {
  26. S->top++;
  27. S->data[S->top] = e;
  28. }
  29. int pop_stack(Stack *S)
  30. {
  31. S->top--;
  32. return S->data[S->top + 1];
  33. }
  34. void init(Graph *G, Dij *D, Stack *S)
  35. {
  36. scanf("%d", &G->Vnum);
  37. for (int i = 0; i < G->Vnum; i++)
  38. {
  39. for (int j = 0; j < G->Vnum; j++)
  40. {
  41. scanf("%d", &G->arc[i][j]);
  42. }
  43. }
  44. for (int i = 0; i < G->Vnum; i++)
  45. {
  46. D->visited[i] = 0;
  47. D->length[i] = G->arc[0][i];
  48. }
  49. D->visited[0] = 1;
  50. S->top = -1;
  51. }
  52. bool is_finished(Graph *G, Dij *D)
  53. {
  54. for (int i = 0; i < G->Vnum; i++)
  55. {
  56. if (!D->visited[i])
  57. {
  58. return false;
  59. }
  60. }
  61. return true;
  62. }
  63. int find_minlength_V(Graph *G, Dij *D)
  64. {
  65. int min = 10005;
  66. int min_V;
  67. for (int i = 0; i < G->Vnum; i++)
  68. {
  69. if (!D->visited[i] && D->length[i] < min)
  70. {
  71. min = D->length[i];
  72. min_V = i;
  73. }
  74. }
  75. return min_V;
  76. }
  77. void update_arc_V(Graph *G, Dij *D, int v)
  78. {
  79. D->visited[v] = true;
  80. for (int i = 0; i < G->Vnum; i++)
  81. {
  82. if (!D->visited[i] && D->length[v] + G->arc[i][v] < D->length[i])
  83. {
  84. D->length[i] = D->length[v] + G->arc[i][v];
  85. }
  86. }
  87. }
  88. void caculate_minlength_for_each_V(Graph *G, Dij *D)
  89. {
  90. for (int i = 0; i < G->Vnum; i++)
  91. {
  92. if (is_finished(G, D))
  93. {
  94. return;
  95. }
  96. int v = find_minlength_V(G, D);
  97. update_arc_V(G, D, v);
  98. }
  99. }
  100. void find_path(Graph *G, Dij *D, Stack *S)
  101. {
  102. int start, end;
  103. scanf("%d%d", &start, &end);
  104. push_stack(S, end);
  105. while (end != start)
  106. {
  107. for (int i = 0; i < G->Vnum; i++)
  108. {
  109. if (G->arc[i][end] != 10000 && D->length[i] < D->length[end] && D->length[i] + G->arc[i][end] == D->length[end])
  110. {
  111. push_stack(S, i);
  112. end = i;
  113. }
  114. }
  115. }
  116. }
  117. void print_path(Stack *S)
  118. {
  119. while (S->top > -1)
  120. {
  121. printf("%d\n", pop_stack(S));
  122. }
  123. }
  124. int main()
  125. {
  126. Graph G;
  127. Dij D;
  128. Stack S;
  129. init(&G, &D, &S);
  130. caculate_minlength_for_each_V(&G, &D);
  131. int path[MAXSIZE];
  132. find_path(&G, &D, &S);
  133. print_path(&S);
  134. return 0;
  135. }
  136. /*
  137. 4
  138. 0 2 10 10000
  139. 2 0 7 3
  140. 10 7 0 6
  141. 10000 3 6 0
  142. 0 2
  143. */

实验4.3 用弗洛伊德算法求赋权图的两点间的最短路径的长度

  1. //010用弗洛伊德算法求赋权图的两点间的最短路径长度
  2. #include <bits/stdc++.h>
  3. #define MAXSIZE 105
  4. #define INF 10000
  5. using namespace std;
  6. typedef struct Graph
  7. {
  8. int vnum;
  9. int arc[MAXSIZE][MAXSIZE];
  10. int path[MAXSIZE][MAXSIZE];
  11. } Graph;
  12. void init_Graph(Graph *G)
  13. {
  14. scanf("%d", &G->vnum);
  15. for (int i = 0; i < G->vnum; i++)
  16. {
  17. for (int j = 0; j < G->vnum; j++)
  18. {
  19. scanf("%d", &G->arc[i][j]);
  20. G->path[i][j] = -1;
  21. }
  22. }
  23. }
  24. void floyd(Graph *G)
  25. {
  26. for (int m = 0; m < G->vnum; m++)
  27. for (int a = 0; a < G->vnum; a++)
  28. for (int b = 0; b < G->vnum; b++)
  29. {
  30. if (G->arc[a][b] > G->arc[a][m] + G->arc[m][b])
  31. {
  32. G->arc[a][b] = G->arc[a][m] + G->arc[m][b];
  33. G->path[a][b] = m;
  34. }
  35. }
  36. }
  37. void print_result(Graph *G)
  38. {
  39. int n;
  40. scanf("%d", &n);
  41. for (int i = 0; i < n; i++)
  42. {
  43. int a, b;
  44. scanf("%d%d", &a, &b);
  45. printf("%d\n", G->arc[a][b]);
  46. }
  47. }
  48. int main()
  49. {
  50. Graph G;
  51. init_Graph(&G);
  52. floyd(&G);
  53. print_result(&G);
  54. return 0;
  55. }
  56. /*
  57. 4
  58. 0 2 10 10000
  59. 2 0 7 3
  60. 10 7 0 6
  61. 10000 3 6 0
  62. 2
  63. 0 2
  64. 3 0
  65. */

实验4.4 用弗洛伊德算法求赋权图中任意两点间的最短路径 

  1. //011用弗洛伊德算法求赋权图任意两点间的最短路径
  2. #include <bits/stdc++.h>
  3. #define MAXSIZE 105
  4. #define INF 10000
  5. using namespace std;
  6. typedef struct Graph
  7. {
  8. int vnum;
  9. int arc[MAXSIZE][MAXSIZE];
  10. int path[MAXSIZE][MAXSIZE];
  11. } Graph;
  12. typedef struct Stack
  13. {
  14. int top;
  15. int data[MAXSIZE];
  16. } Stack;
  17. void init_Stack(Stack *S)
  18. {
  19. S->top = -1;
  20. }
  21. void push_Stack(Stack *S, int e)
  22. {
  23. S->top++;
  24. S->data[S->top] = e;
  25. }
  26. int pop_Stack(Stack *S)
  27. {
  28. S->top--;
  29. return S->data[S->top + 1];
  30. }
  31. void init_Graph(Graph *G)
  32. {
  33. scanf("%d", &G->vnum);
  34. for (int i = 0; i < G->vnum; i++)
  35. {
  36. for (int j = 0; j < G->vnum; j++)
  37. {
  38. scanf("%d", &G->arc[i][j]);
  39. G->path[i][j] = -1;
  40. }
  41. }
  42. }
  43. void floyd(Graph *G)
  44. {
  45. for (int m = 0; m < G->vnum; m++)
  46. for (int a = 0; a < G->vnum; a++)
  47. for (int b = 0; b < G->vnum; b++)
  48. {
  49. if (G->arc[a][b] > G->arc[a][m] + G->arc[m][b])
  50. {
  51. G->arc[a][b] = G->arc[a][m] + G->arc[m][b];
  52. G->path[a][b] = m;
  53. }
  54. }
  55. }
  56. void find_path(Graph *G, Stack *S, int a, int b)
  57. {
  58. push_Stack(S, b);
  59. if (G->path[a][b] == -1)
  60. {
  61. push_Stack(S, a);
  62. return;
  63. }
  64. else
  65. {
  66. find_path(G, S, a, G->path[a][b]);
  67. }
  68. }
  69. void print_result(Graph *G, Stack *S)
  70. {
  71. int n;
  72. scanf("%d", &n);
  73. for (int i = 0; i < n; i++)
  74. {
  75. int a, b;
  76. scanf("%d%d", &a, &b);
  77. init_Stack(S);
  78. find_path(G, S, a, b);
  79. while (S->top > -1)
  80. {
  81. printf("%d\n", pop_Stack(S));
  82. }
  83. }
  84. }
  85. int main()
  86. {
  87. Graph G;
  88. Stack S;
  89. init_Graph(&G);
  90. floyd(&G);
  91. print_result(&G, &S);
  92. return 0;
  93. }
  94. /*
  95. 4
  96. 0 2 10 10000
  97. 2 0 7 3
  98. 10 7 0 6
  99. 10000 3 6 0
  100. 2
  101. 0 2
  102. 3 0
  103. */

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/734791
推荐阅读
相关标签
  

闽ICP备14008679号