数据结构复习


一、单链表合并。

第一版

#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;
}

六、查找

1、静态查找

2、二叉排序树

3、平衡二叉排序树

4、哈希查找(散列表)

七、排序

1.直接插入

2.选择排序

3.冒泡排序

4.快速排序

5.基数排序

6.二路归并排序

7.大顶堆、小顶堆

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值