文章目录
一、单链表合并。
第一版
#include<iostream>
using namespace std;
#define ok 0
#define error -1
class ListNode
{
public:
int data;
ListNode* next;
ListNode()
{
next = NULL;
}
};
class LinkList
{
private:
ListNode* head;
int len;
public:
LinkList();
~LinkList();
ListNode* LL_index(int i);
int LL_get(int i);
int LL_insert(int i, int item);
int LL_del(int i);
void LL_display();
void LL_add(LinkList& b);
};
LinkList::LinkList()
{
head = new ListNode();
len = 0;
}
int LinkList::LL_insert(int i, int item)
{
if (i <= 0 || i > len + 1)
{
return error;
}
ListNode* p;
ListNode* s;
p = LL_index(i - 1);
s = new ListNode();
s->data = item;
s->next = p->next;
p->next = s;
len++;
return ok;
}
int LinkList::LL_get(int i)
{
if (i <= 0 || i > len)
{
return error;
}
ListNode* p;
p = head;
int j = 0;
while (p && j < i)
{
p = p->next;
j++;
}
if (!p)
{
return error;
}
else
return p->data;
}
ListNode* LinkList::LL_index(int i)
{
int j = 0;
ListNode* p = head;
while (p && j < i)
{
p = p->next;
j++;
}
if (!p)
{
return NULL;
}
else
return p;
}
LinkList::~LinkList()
{
ListNode* p, * q;
p = head;
while (p != NULL)
{
q = p;
p = p->next;
delete q;
}
len = 0;
head = NULL;
}
int LinkList::LL_del(int i)
{
if (i <= 0 || i >= len)
{
return error;
}
ListNode* p;
ListNode* s;
p = LL_index(i - 1);
s = p->next;
p->next = s->next;
delete s;
len--;
return ok;
}
void LinkList::LL_display()
{
ListNode* p;
p = head->next;
while (p)
{
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
void LinkList::LL_add(LinkList& b)
{
LinkList c;
int length = len + b.len;
int i = 1;
int j = 1;
int k = 1;
int tempa;
int tempb;
while (j <= len && k <= b.len)
{
tempa = LL_get(j);
tempb = b.LL_get(k);
if (tempa < tempb)
{
c.LL_insert(i, tempa);
i++;
j++;
}
else
{
c.LL_insert(i, tempb);
i++;
k++;
}
}
while (j > len && i <= length)
{
c.LL_insert(i, b.LL_get(k));
i++;
k++;
}
while (k > b.len && i <= length)
{
c.LL_insert(i, LL_get(j));
j++;
i++;
}
c.LL_display();
}
int main()
{
int n;
cin >> n;
LinkList a;
LinkList b;
int temp;
for (int i = 1; i <= n; i++)
{
cin >> temp;
a.LL_insert(i, temp);
}
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> temp;
b.LL_insert(i, temp);
}
a.LL_add(b);
}
第二版
#include<iostream>
using namespace std;
class Node
{
public:
Node* next;
int data;
Node();
};
Node::Node()
{
data = 0;
next = NULL;
}
class List
{
private:
Node* head;
int len;
public:
List();
void creat(int n);
void display();
void merge(List b);
};
List::List()
{
head = new Node();
len = 0;
}
void List::merge(List b)
{
Node* p = head;
Node* ta = head->next;
Node* tb = b.head->next;
int i = 0;
int j = 0;
while (i < len && j < b.len)
{
if (ta->data > tb->data)
{
Node* t = new Node();
t = tb;
p->next = t;
p = t;
tb = tb->next;
j++;
}
else if (ta->data < tb->data)
{
Node* t = new Node();
t = ta;
p->next = t;
p = t;
ta = ta->next;
i++;
}
}
while (i < len)
{
p->next = ta;
i++;
p = p->next;
ta = ta->next;
}
while (j < b.len)
{
tb->data;
p->next = tb;
j++;
p = p->next;
tb = tb->next;
}
len += b.len;
}
void List::creat(int n)
{
len = n;
int t;
Node* q = head;
while (n--)
{
Node* p = new Node();
cin >> t;
p->data = t;
q->next = p;
q = q->next;
}
}
void List::display()
{
Node* p = head->next;
for (int i = 1; i <= len; i++)
{
cout << p->data << " ";
p = p->next;
}
}
int main()
{
int n;
cin >> n;
List a;
a.creat(n);
List b;
cin >> n;
b.creat(n);
a.merge(b);
a.display();
}
总结
1)
第一是在学期初刚刚接触单链表时所写,建立链表和合并链表都是依靠插入。第二在建立链表时,空出了哑节点。在合并时,从表头开始同时遍历两链表,将当前已完成的表尾元素的后继节点设置为当前A和B游标中较小一个,并将游标后移一位。
2)
在对链表进行插入或删除工作时,应对所给的位置进行判断。
3)
多维数组地址计算
二、栈和队列
1.可能的出栈序列
解决方法:
可以看A出栈的位置,A首先出栈,剩下的3个元素出栈不受影响,可以看作3个元素出栈序列的种数。A在第二位出栈,就确定了B第一个出栈;在第三位出栈就确定了D在第四位出栈,另外两个元素的出栈不受影响,可以看作3个元素出栈序列的种数,A在第四位出栈同第一位的情况。
2.循环队列
能够避免假溢出现象。
3.利用栈将递归函数化为非递归函数
三、树
1.二叉树的节点、叶子数相关
首先可知层数为10,故1-9层为满二叉树。可知第10层中叶子节点数量,又因为每两个叶子节点对应一个根节点,可知第九层中根节点数目,可求得第九层叶子节点数。
2.树和森林转化为二叉树
3.遍历树代码
#include<iostream>
#include<string>
using namespace std;
class BiTreeNode
{
public:
char data;
BiTreeNode* LeftChild;
BiTreeNode* RightChild;
BiTreeNode() :LeftChild(NULL), RightChild(NULL) {}
~BiTreeNode() {}
};
class BiTree
{
private:
BiTreeNode* Root;
int pos;
string strTree;
BiTreeNode* CreatBiTree();
void PreOrder(BiTreeNode* t);
void InOrder(BiTreeNode* t);
void PostOrder(BiTreeNode* t);
public:
BiTree() {}
~BiTree() {}
void CreateTree(string TreeArray);
void PreOrder();
void InOrder();
void PostOrder();
};
void BiTree::CreateTree(string TreeArray)
{
pos = 0;
strTree.assign(TreeArray);
Root = CreatBiTree();
}
BiTreeNode* BiTree::CreatBiTree()
{
BiTreeNode* T;
char ch;
ch = strTree[pos++];
if (ch == '0')
{
T = NULL;
}
else
{
T = new BiTreeNode();
T->data = ch;
T->LeftChild = CreatBiTree();
T->RightChild = CreatBiTree();
}
return T;
}
void BiTree::PreOrder()
{
PreOrder(Root);
}
void BiTree::PreOrder(BiTreeNode* t)
{
if (t != NULL)
{
cout << t->data;
PreOrder(t->LeftChild);
PreOrder(t->RightChild);
}
}
void BiTree::InOrder()
{
InOrder(Root);
}
void BiTree::InOrder(BiTreeNode* t)
{
if (t)
{
InOrder(t->LeftChild);
cout << t->data;
InOrder(t->RightChild);
}
}
void BiTree::PostOrder()
{
PostOrder(Root);
}
void BiTree::PostOrder(BiTreeNode* t)
{
if (t)
{
PostOrder(t->LeftChild);
PostOrder(t->RightChild);
cout << t->data;
}
}
int main()
{
int t;
cin >> t;
BiTree* tree;
while (t--)
{
string s;
cin >> s;
tree = new BiTree();
tree->CreateTree(s);
tree->PreOrder();
cout << endl;
tree->InOrder();
cout << endl;
tree->PostOrder();
cout << endl;
}
return 0;
}
4.哈夫曼编码
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
const int MaxW = 9999999; // 假设结点权值不超过9999999
// 定义huffman树结点类
class HuffNode
{
public:
int weight; // 权值
int parent; // 父结点下标
int leftchild; // 左孩子下标
int rightchild; // 右孩子下标
};
// 定义赫夫曼树类
class HuffMan
{
private:
void MakeTree(); // 建树,私有函数,被公有函数调用
void SelectMin(int pos, int* s1, int* s2); // 从 1 到 pos 的位置找出权值最小的两个结点,
// 把结点下标存在 s1 和 s2 中
public:
int len; // 结点数量
int lnum; // 叶子数量
HuffNode* huffTree; // 赫夫曼树,用数组表示
string* huffCode; // 每个字符对应的赫夫曼编码
void MakeTree(int n, int wt[]); // 公有函数,被主函数main调用
void Coding(); // 公有函数,被主函数main调用
void Destroy();
};
// 构建huffman树
void HuffMan::MakeTree(int n, int wt[])
{
// 参数是叶子结点数量和叶子权值
// 公有函数,对外接口
int i;
lnum = n;
len = 2 * n - 1;
huffTree = new HuffNode[2 * n];
huffCode = new string[lnum + 1]; // 位置从 1 开始计算
// huffCode实质是个二维字符数组,第 i 行表示第 i 个字符对应的编码
// 赫夫曼树huffTree初始化
for (i = 1; i <= n; i++)
huffTree[i].weight = wt[i - 1]; // 第0号不用,从1开始编号
for (i = 1; i <= len; i++)
{
if (i > n) huffTree[i].weight = 0; // 前n个结点是叶子,已经设置
huffTree[i].parent = 0;
huffTree[i].leftchild = 0;
huffTree[i].rightchild = 0;
}
MakeTree(); // 调用私有函数建树
}
void HuffMan::SelectMin(int pos, int* s1, int* s2)
{
// 找出最小的两个权值的下标
// 函数采用地址传递的方法,找出两个下标保存在 s1 和 s2 中
int w1, w2, i;
w1 = w2 = MaxW; // 初始化w1和w2为最大值,在比较中会被实际的权值替换
*s1 = *s2 = 0;
for (i = 1; i <= pos; i++)
{
// 比较过程如下:
// 如果第 i 个结点的权值小于 w1,且第 i 个结点是未选择的结点,提示:如果第 i 结点未选择,它父亲为 0
// 把第 w1 和 s1 保存到 w2 和 s2,即原来的第一最小值变成第二最小值
// 把第 i 结点的权值和下标保存到 w1 和 s1,作为第一最小值
// 否则,如果第 i 结点的权值小于 w2,且第 i 结点是未选择的结点
// 把第 i 结点的权值和下标保存到 w2 和 s2,作为第二最小值
if (w1 > huffTree[i].weight && !huffTree[i].parent) {
w2 = w1;
*s2 = *s1;
w1 = huffTree[i].weight;
*s1 = i;
}
else if (w2 > huffTree[i].weight && !huffTree[i].parent) {
w2 = huffTree[i].weight;
*s2 = i;
}
}
}
void HuffMan::MakeTree()
{
// 私有函数,被公有函数调用
int i, s1, s2;
for (i = lnum + 1; i <= len; i++)
{
SelectMin(i - 1, &s1, &s2); // 找出两个最小权值的下标放入 s1 和 s2 中
// 将找出的两棵权值最小的子树合并为一棵子树,过程包括
// 结点 s1 和结点 s2 的父亲设为 i
// 结点 i 的左右孩子分别设为 s1 和 s2
huffTree[s1].parent = huffTree[s2].parent = i;
huffTree[i].leftchild = s1;
huffTree[i].rightchild = s2;
// 结点 i 的权值等于 s1 和 s2 的权值和
huffTree[i].weight = huffTree[s1].weight + huffTree[s2].weight;
}
}
// 销毁赫夫曼树
void HuffMan::Destroy()
{
len = 0;
lnum = 0;
delete[]huffTree;
delete[]huffCode;
}
// 赫夫曼编码
void HuffMan::Coding()
{
char* cd;
int i, c, f, start;
// 求 n 个结点的赫夫曼编码
cd = new char[lnum]; // 分配求编码的工作空间
cd[lnum - 1] = '\0'; // 编码结束符
for (i = 1; i <= lnum; ++i)
{
// 逐个字符求赫夫曼编码
start = lnum - 1; // 编码结束符位置
// 参考课本P147算法6.12 HuffmanCoding代码
for (c = i, f = huffTree[i].parent; f != 0; c = f, f = huffTree[f].parent)
if (huffTree[f].leftchild == c) {
cd[--start] = '0';
}
else {
cd[--start] = '1';
}
huffCode[i].assign(&cd[start]); // 把cd中从start到末尾的编码复制到huffCode中
}
delete[]cd; // 释放工作空间
}
// 主函数
int main()
{
int t, n, i, j;
int wt[800];
HuffMan myHuff;
cin >> t;
for (i = 0; i < t; i++)
{
cin >> n;
for (j = 0; j < n; j++)
cin >> wt[j];
myHuff.MakeTree(n, wt);
myHuff.Coding();
for (j = 1; j <= n; j++)
{
cout << myHuff.huffTree[j].weight << '-'; // 输出各权值
cout << myHuff.huffCode[j] << endl; // 输出各编码
}
myHuff.Destroy();
}
return 0;
}
五、哈夫曼解码
#include<iostream>
#include<string>
#include<cstring>
#define ok 1
#define error -1
using namespace std;
const int MaxW = 9999999; // 假设结点权值不超过9999999
// 定义huffman树结点类
class HuffNode
{
public:
char cha;
int weight; // 权值
int parent; // 父结点下标
int leftchild; // 左孩子下标
int rightchild; // 右孩子下标
};
// 定义赫夫曼树类
class HuffMan
{
private:
void MakeTree(); // 建树,私有函数,被公有函数调用
void SelectMin(int pos, int* s1, int* s2); // 从 1 到 pos 的位置找出权值最小的两个结点,
// 把结点下标存在 s1 和 s2 中
public:
int len; // 结点数量
int lnum; // 叶子数量
HuffNode* huffTree; // 赫夫曼树,用数组表示
string* huffCode; // 每个字符对应的赫夫曼编码
void MakeTree(int n, int wt[], char ct[]); // 公有函数,被主函数main调用
void Coding(); // 公有函数,被主函数main调用
int Decode(const string codestr, char txtstr[]);
void Destroy();
};
// 构建huffman树
void HuffMan::MakeTree(int n, int wt[], char ct[])
{
// 参数是叶子结点数量和叶子权值
// 公有函数,对外接口
int i;
lnum = n;
len = 2 * n - 1;
huffTree = new HuffNode[n * 2];
huffCode = new string[lnum + 1]; // 位置从 1 开始计算
// huffCode实质是个二维字符数组,第 i 行表示第 i 个字符对应的编码
// 赫夫曼树huffTree初始化
for (i = 1; i <= n; i++)
{
huffTree[i].weight = wt[i - 1]; // 第0号不用,从1开始编号
huffTree[i].cha = ct[i - 1];
}
for (i = 1; i <= len; i++)
{
if (i > n)
{
huffTree[i].cha = '0';
huffTree[i].weight = 0; // 前n个结点是叶子,已经设置
}
huffTree[i].parent = 0;
huffTree[i].leftchild = 0;
huffTree[i].rightchild = 0;
}
MakeTree(); // 调用私有函数建树
}
void HuffMan::SelectMin(int pos, int* s1, int* s2)
{
// 找出最小的两个权值的下标
// 函数采用地址传递的方法,找出两个下标保存在 s1 和 s2 中
int w1, w2, i;
w1 = w2 = MaxW; // 初始化w1和w2为最大值,在比较中会被实际的权值替换
*s1 = *s2 = 0;
for (i = 1; i <= pos; i++)
{
// 比较过程如下:
// 如果第 i 个结点的权值小于 w1,且第 i 个结点是未选择的结点,提示:如果第 i 结点未选择,它父亲为 0
// 把第 w1 和 s1 保存到 w2 和 s2,即原来的第一最小值变成第二最小值
// 把第 i 结点的权值和下标保存到 w1 和 s1,作为第一最小值
// 否则,如果第 i 结点的权值小于 w2,且第 i 结点是未选择的结点
// 把第 i 结点的权值和下标保存到 w2 和 s2,作为第二最小值
if (w1 > huffTree[i].weight && !huffTree[i].parent) {
w2 = w1;
*s2 = *s1;
w1 = huffTree[i].weight;
*s1 = i;
}
else if (w2 > huffTree[i].weight && !huffTree[i].parent) {
w2 = huffTree[i].weight;
*s2 = i;
}
}
}
void HuffMan::MakeTree()
{
// 私有函数,被公有函数调用
int i, s1, s2;
for (i = lnum + 1; i <= len; i++)
{
SelectMin(i - 1, &s1, &s2);
// 找出两个最小权值的下标放入 s1 和 s2 中
// 将找出的两棵权值最小的子树合并为一棵子树,过程包括
// 结点 s1 和结点 s2 的父亲设为 i
// 结点 i 的左右孩子分别设为 s1 和 s2
huffTree[s1].parent = huffTree[s2].parent = i;
huffTree[i].leftchild = s1;
huffTree[i].rightchild = s2;
// 结点 i 的权值等于 s1 和 s2 的权值和
huffTree[i].weight = huffTree[s1].weight + huffTree[s2].weight;
}
}
// 销毁赫夫曼树
void HuffMan::Destroy()
{
len = 0;
lnum = 0;
delete[]huffTree;
delete[]huffCode;
}
// 赫夫曼编码
void HuffMan::Coding()
{
char* cd;
int i, c, f, start;
// 求 n 个结点的赫夫曼编码
cd = new char[lnum]; // 分配求编码的工作空间
cd[lnum - 1] = '\0'; // 编码结束符
for (i = 1; i <= lnum; ++i)
{
// 逐个字符求赫夫曼编码
start = lnum - 1; // 编码结束符位置
// 参考课本P147算法6.12 HuffmanCoding代码
for (c = i, f = huffTree[i].parent; f != 0; c = f, f = huffTree[f].parent)
{
if (huffTree[f].leftchild == c)
{
cd[--start] = '0';
}
else
{
cd[--start] = '1';
}
}
huffCode[i] = new char[lnum - start];
huffCode[i].assign(&cd[start]); // 把cd中从start到末尾的编码复制到huffCode中
}
delete[]cd; // 释放工作空间
}
//赫夫曼解码
int HuffMan::Decode(const string codestr, char txtstr[])
{
int i, k, c;
char ch;
c = len;
k = 0;
for (i = 0; i < codestr.length(); i++)
{
ch = codestr[i];
if (ch == '0')
{
c = huffTree[c].leftchild;
}
else if (ch == '1')
{
c = huffTree[c].rightchild;
}
else if (ch != '1' && ch != '0')
{
return error;
}
if (huffTree[c].leftchild == 0 && huffTree[c].rightchild == 0)
{
txtstr[k++] = huffTree[c].cha;
c = len;
}
else
{
ch = '\0';
}
}
if (ch == '\0') return error;
else txtstr[k] = '\0';
return ok;
}
// 主函数
int main()
{
int t, n, i, j;
int wt[800];
char ct[800];
HuffMan myHuff;
cin >> t;
while (t--)
{
cin >> n;
for (j = 0; j < n; j++)
{
cin >> wt[j];
}
for (j = 0; j < n; j++) {
cin >> ct[j];
}
myHuff.MakeTree(n, wt, ct);
myHuff.Coding();
int k;
string codestr;
cin >> k;
char txtstr[800];
while (k--)
{
cin >> codestr;
if (myHuff.Decode(codestr, txtstr) == 1)
{
cout << txtstr << endl;
}
else
{
cout << "error" << endl;
}
}
myHuff.Destroy();
}
return 0;
}
四、图
1.存储
1)矩阵(适用稠密图)
2)链表(适用稀疏图)
2.遍历
1.DFS
#include<iostream>
using namespace std;
const int MaxLen = 20;
class Map
{
private:
bool Visit[MaxLen];
int Matrix[MaxLen][MaxLen];
int Vexnum;
void DFS(int v);
public:
void SetMatrix(int vnum, int mx[MaxLen][MaxLen]);
void DFSTraverse();
};
void Map::SetMatrix(int vnum, int mx[MaxLen][MaxLen])
{
int i, j;
Vexnum = vnum;
for (int i = 0; i < MaxLen; i++)
{
for (int j = 0; j < MaxLen; j++)
{
Matrix[i][j] = 0;
}
}
for (i = 0; i < Vexnum; i++)
{
for (j = 0; j < Vexnum; j++)
{
Matrix[i][j] = mx[i][j];
}
}
}
void Map::DFSTraverse()
{
int v;
for (v = 0; v < Vexnum; v++)
{
Visit[v] = false;
}
for (v = 0; v < Vexnum; v++)
{
if (Visit[v] == false)
{
DFS(v);
}
}
}
void Map::DFS(int v)
{
int w, i, k;
Visit[v] = true;
cout << v << " ";
int* Adjvex = new int[Vexnum];
for (i = 0; i < Vexnum; i++)
{
Adjvex[i] = -1;
}
k = 0;
for (i = 0; i < Vexnum; i++)
{
if (Matrix[v][i] == 1)
{
Adjvex[k++] = i;
}
}
i = 0;
for (w = Adjvex[i]; w >= 0; w = Adjvex[++i])
{
if (!Visit[w])
DFS(w);
}
delete[]Adjvex;
}
int main()
{
int t, n;
cin >> t;
while (t--)
{
cin >> n;
Map a;
int m[MaxLen][MaxLen];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
int temp;
cin >> temp;
m[i][j] = temp;
}
}
a.SetMatrix(n, m);
a.DFSTraverse();
cout << endl;
}
return 0;
}
2.BFS
代码:
#include<iostream>
#include<queue>
using namespace std;
const int MaxLen = 20;
class Map
{
private:
bool Visit[MaxLen];
int Matrix[MaxLen][MaxLen];
int Vexnum;
void DFS(int v);
void BFS(int v);
public:
void SetMatrix(int vnum, int mx[MaxLen][MaxLen]);
void DFSTraverse();
void BFSTraverse();
};
void Map::BFSTraverse()
{
BFS(0);
}
void Map::BFS(int v)
{
int w, u;
int i, k;
queue<int> Q;
i = 0;
for (v = 0; v < Vexnum; ++v)
{
if (!Visit[v])
{
Visit[v] = true;
cout << v << " ";
Q.push(v);
while (!Q.empty())
{
u = Q.front();
Q.pop();
for (w = 0; w < Vexnum; w++) {
if (Matrix[w][u] == 1 && Visit[w] == 0) {
cout << w << " ";
Visit[w] = 1;
Q.push(w);
}
}
}
}
}
}
void Map::SetMatrix(int vnum, int mx[MaxLen][MaxLen])
{
int i, j;
Vexnum = vnum;
for (int i = 0; i < MaxLen; i++)
{
for (int j = 0; j < MaxLen; j++)
{
Matrix[i][j] = 0;
}
}
for (i = 0; i < Vexnum; i++)
{
for (j = 0; j < Vexnum; j++)
{
Matrix[i][j] = mx[i][j];
}
}
}
int main()
{
int t, n;
cin >> t;
while (t--)
{
cin >> n;
Map a;
int m[MaxLen][MaxLen];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
int temp;
cin >> temp;
m[i][j] = temp;
}
}
a.SetMatrix(n, m);
//a.DFSTraverse();
a.BFSTraverse();
cout << endl;
}
return 0;
}
3.最小生成树
代码:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void prim(int** m, string* s, int n, string start_point)
{
int* visit = new int[n];
for (int i = 0; i < n; i++)
visit[i] = 0;
struct {
string adj;
int lowcost;
}closedge[n];
int temp;
for (int i = 0; i < n; i++)
{
temp = m[i][0];
closedge[i].adj = s[0];
closedge[i].lowcost = temp;
for (int j = 1; j < n; j++)
{
if (temp > m[i][j])
{
temp = m[i][j];
closedge[i].adj = s[j];
closedge[i].lowcost = temp;
}
}
}
for (int i = 0; i < n; i++)
{
if (s[i] == start_point)
{
visit[i] = 1;
break;
}
}
int mmin, loc;
string t;
vector<string> v_one;
vector<string> v_two;
vector<int> the_min;
for (int i = 0; i < n - 1; i++)
{
mmin = 100000000;
for (int j = 0; j < n; j++)
{
if (visit[j] != 1)
continue;
else
{
if (mmin > closedge[j].lowcost)
{
mmin = closedge[j].lowcost;
t = closedge[j].adj;
loc = j;
}
}
}
v_one.push_back(s[loc]);
v_two.push_back(t);
the_min.push_back(mmin);
for (int i = 0; i < n; i++)
{
if (s[i] == t)
{
visit[i] = 1;
m[loc][i] = 10000000;
m[i][loc] = 10000000;
break;
}
}
for (int i = 0; i < n; i++)
{
temp = m[i][0];
closedge[i].adj = s[0];
closedge[i].lowcost = temp;
for (int j = 1; j < n; j++)
{
if (temp > m[i][j] && visit[j] != 1)
{
temp = m[i][j];
closedge[i].adj = s[j];
closedge[i].lowcost = temp;
}
}
}
}
int last = 0;
for (int i = 0; i < v_one.size(); i++)
last += the_min[i];
cout << last << endl;
cout << "prim:" << endl;
for (int i = 0; i < v_one.size(); i++)
{
cout << v_one[i] << ' ' << v_two[i] << ' ' << the_min[i] << endl;
}
delete[]visit;
}
void kruskal(int** m, string* s, int n)
{
cout << "kruskal:" << endl;
int* father = new int[n];
for (int i = 0; i < n; i++)
father[i] = i;
int temp_min;
string s1, s2;
int loc1, loc2;
for (int i = 0; i < n - 1; i++)
{
temp_min = 10000000;
for (int j = 0; j < n; j++)
{
for (int k = 0; k < n; k++)
{
if (father[j] == father[k])
continue;
else
{
if (temp_min > m[j][k])
{
temp_min = m[j][k];
loc1 = j;
loc2 = k;
}
}
}
}
m[loc1][loc2] = 10000000;
m[loc2][loc1] = 10000000;
if (loc1 > loc2)
{
cout << s[loc2] << ' ' << s[loc1] << ' ' << temp_min << endl;
for (int i = 0; i < n; i++)
{
if (father[i] == father[loc1] && i != loc1)
father[i] = father[loc2];
}
father[loc1] = father[loc2];
}
else
{
cout << s[loc1] << ' ' << s[loc2] << ' ' << temp_min << endl;
for (int i = 0; i < n; i++)
{
if (father[i] == father[loc2] && i != loc2)
father[i] = father[loc1];
}
father[loc2] = father[loc1];
}
}
delete[]father;
}
void test(int n)
{
int k;
string* s = new string[n];
for (int i = 0; i < n; i++)
cin >> s[i];
int** m, ** m1;
m = new int* [n];
m1 = new int* [n];
for (int i = 0; i < n; i++)
{
m[i] = new int[n];
m1[i] = new int[n];
for (int j = 0; j < n; j++)
{
m[i][j] = 10000000;
m1[i][j] = 10000000;
}
}
cin >> k;
string temp1, temp2;
int flag1, flag2, cost;
for (int i = 0; i < k; i++)
{
cin >> temp1 >> temp2 >> cost;
for (int p = 0; p < n; p++)
{
if (s[p] == temp1)
flag1 = p;
if (s[p] == temp2)
flag2 = p;
}
m[flag1][flag2] = cost;
m[flag2][flag1] = cost;
m1[flag1][flag2] = cost;
m1[flag2][flag1] = cost;
}
string start_point;
cin >> start_point;
prim(m, s, n, start_point);
kruskal(m1, s, n);
delete[]m;
delete[]m1;
delete[]s;
}
int main()
{
int t;
while (cin >> t)
test(t);
return 0;
}
1.Prim算法
2.Kruskal算法
4.从一个点出发的最短路径
1.迪杰斯特拉
1)代码实现
#include <iostream>
#include <string>
#define Max 99999
using namespace std;
class Graph
{
int ver_num;
int **adjacency;
string *ver;
string start;
string *Path;
public:
Graph()
{
cin >> ver_num;
ver = new string[ver_num];
Path = new string[ver_num];
for (int i = 0; i < ver_num; i++)
{
cin >> ver[i];
adjacency = new int *[ver_num];
}
for (int i = 0; i < ver_num; i++)
{
adjacency[i] = new int[ver_num];
for (int j = 0; j < ver_num; j++)
{
cin >> adjacency[i][j];
if (adjacency[i][j] == 0)
adjacency[i][j] = Max;
}
}
cin >> start;
}
int Index(string a)
{
for (int i = 0; i < ver_num; i++)
if (a == ver[i])
return i;
return -1;
}
void Dijkstra()
{
int i, j, Current, min;
bool *Final = new bool[ver_num];
int *Dest = new int[ver_num];
int index = Index(start);
for (int i = 0; i < ver_num; i++)
{
Path[i] = start + " ";
Dest[i] = adjacency[index][i];
Final[i] = false;
}
Dest[index] = 0;
Final[index] = true;
for (i = 0; i < ver_num - 1; i++)
{
min = Max;
Current = -1;
for (j = 0; j < ver_num; j++)
{
if (Final[j] == false && min > Dest[j])
{
Current = j;
min = Dest[j];
}
}
if (Current != -1)
{
Final[Current] = true;
Path[Current] += ver[Current] + " ";
for (int q = 0; q < ver_num; q++)
{
if (Final[q] == false && min + adjacency[Current][q] < Dest[q])
{
Dest[q] = min + adjacency[Current][q];
Path[q] = Path[Current];
}
}
}
}
for (int i = 1; i < ver_num; i++)
{
cout << ver[0] << "-" << ver[i];
if (Dest[i] >= Max)
{
cout << "--1" << endl;
continue;
}
cout << "-" << Dest[i] << "----[" << Path[i] << "]" << endl;
}
}
};
int main()
{
int t;
cin >> t;
while (t--)
{
Graph MyGraph;
MyGraph.Dijkstra();
}
return 0;
}
2)
5.AOV网络
1.拓扑排序
#include<iostream>
using namespace std;
class Graph
{
private:
int n;
int** matrix;
int* visit;
void find();
public:
Graph(int n);
void display();
};
Graph::Graph(int N)
{
n = N;
visit = new int[n];
for (int i = 0; i < n; i++)
{
visit[i] = -1;
}
matrix = new int* [n];
for (int i = 0; i < n; i++)
{
matrix[i] = new int[n];
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> matrix[i][j];
}
}
}
void Graph::find()
{
for (int i = 0; i < n; i++)
{
if (visit[i] != 1)
{
int flag = 0;
for (int j = 0; j < n; j++)
{
if (matrix[j][i] == 1)
{
flag = 1;
}
}
if (flag == 0)
{
cout << i << " ";
visit[i] = 1;
for (int j = 0; j < n; j++)
{
matrix[i][j] = 0;
}
find();
}
}
}
}
void Graph::display()
{
find();
for (int i = 0; i < n; i++)
{
if (visit[i] == -1)
{
cout << i << " ";
}
}
cout << endl;
}
int main()
{
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
Graph a(n);
a.display();
}
return 0;
}
6.AOE网络
五、串
1、KMP算法
#include <iostream>
#include <string>
using namespace std;
class myString {
private:
string mainstr;
int size;
void GetNext(string p, int next[]) {
next[0] = -1;
next[1] = 0;
int L = p.length();
int temp = 0;
for (int i = 2; i < L; i++) {
while (p[i - 1] != p[temp] && temp > 0) {
temp = next[temp];
}
if (p[i - 1] == p[temp]) {
temp++;
}
next[i] = temp;
}
}
int KMPFind(string p, int pos, int next[]) {
int i = pos, j = 0;
while (mainstr[i] != '\0' && p[j] != '\0') {
if (mainstr[i] == p[j]) {
++i;
++j;
}
else {
j = next[j];
}
if (j == -1) {
++i;
++j;
}
}
if (p[j] == '\0')
return i - j;
else
return -1;
}
public:
myString() { size = 0; mainstr = ""; }
~myString() { size = 0; mainstr = ""; }
void SetVal(string sp) {
mainstr = "";
mainstr.assign(sp);
size = mainstr.length();
}
int KMPFindSubstr(string p, int pos) {
int i;
int L = p.length();
int* next = new int[L];
GetNext(p, next);
for (i = 0; i < L; i++) {
cout << next[i] << ' ';
}
cout << endl;
int v = -1;
v = KMPFind(p, 0, next);
delete[] next;
return v;
}
};
int main()
{
int t;
cin >> t;
while (t--)
{
string templet;
cin >> templet;
string target;
cin >> target;
myString str;
str.SetVal(templet);
cout << str.KMPFindSubstr(target, 0) + 1 << endl;
}
return 0;
}