链表基本操作
#include<cstdio>
#include<cstring>
struct Node {
int val;
Node* next;
};
// 尾插
void add(Node* &head, Node* &fail, int val)
{
Node* p = new Node();
p->val = val;
p->next = NULL;
if (head == NULL)
{
head = fail = p;
}
else
{
fail->next = p;
fail = p;
}
}
void print(Node* head)
{
for(Node *p = head; p != NULL; p = p->next) printf("%d ", p->val); puts("");
}
// 归并两个有序链表返回头节点
Node* merge(Node* headA, Node* headB)
{
if(headA == NULL) return headB;
if(headB == NULL) return headA;
Node *p1 = headA, *p2 = headB, *resHead = headA;
if(p2->val < p1->val)
{
resHead = p2;
p2 = p2->next;
}
else
{
p1 = p1->next;
}
Node *p = resHead;
while(p1 != NULL and p2 != NULL)
{
if(p1->val <= p2->val)
{
p->next = p1;
p1 = p1->next;
}
else
{
p->next = p2;
p2 = p2->next;
}
p = p->next;
}
if(p1 != NULL) p->next = p1;
if(p2 != NULL) p->next = p2;
return resHead;
}
int main()
{
Node *headA = NULL, *failA = NULL;
Node *headB = NULL, *failB = NULL;
int n, a[10];
scanf("%d", &n);
for(int i = 0; i < n; i ++)
{
scanf("%d", &a[i]);
add(headA, failA, a[i]);
}
print(headA);
scanf("%d", &n);
for(int i = 0; i < n; i ++)
{
scanf("%d", &a[i]);
add(headB, failB, a[i]);
}
print(headB);
Node* list = merge(headA, headB);
print(list);
return 0;
}
/***
输入数据
3
1 3 5
4
2 4 6 8
输出数据
1 3 5
2 4 6 8
1 2 3 4 5 6 8
***/
树
确定树的形态:中序遍历 + 后续遍历、前序遍历、层序遍历三种之中任何一种。
线索化二叉树就是根据遍历顺序确定前驱和后继,引入标志域 l t a g ltag ltag 和 r t a g rtag rtag,当标志域为 0 指示结点的左( l t a g ltag ltag)/右( r t a g rtag rtag)孩子,当标志域为 1 指示结点的前驱( l t a g ltag ltag)/后继( r t a g rtag rtag)。
哈夫曼合并总共合并 n − 1 n-1 n−1 次,哈夫曼树形态不同,但是 带权路径长度( W P L WPL WPL) 相同, W P L WPL WPL = 哈夫曼树中每个的叶子结点权值 × \times ×路径长度之和。
平衡二叉树:左右子树高度差的绝对值不超过 1
二叉排序树:左儿子权值
<
<
< 根
<
<
< 右儿子
问题:设以
n
h
n_h
nh 表示深度为
h
h
h 的平衡树中含有的最少的结点数?
设
n
0
n_0
n0 = 0,
n
1
n_1
n1 = 1,
n
2
n_2
n2 = 2,并且有
n
h
n_h
nh =
n
h
−
1
n_{h-1}
nh−1 +
n
h
−
2
n_{h-2}
nh−2 + 1
哈夫曼无前缀编码:没有一个编码是另一个编码的前缀。
平均查找长度(ASL):长度 ÷ \div ÷ 结点数
图
最小生成树( M S T MST MST)
最小生成树不是唯一的
最小生成树的边的权值之和总是唯一的
最小生成树的边数为顶点数减 1
P
r
i
m
Prim
Prim 和
K
r
u
s
k
a
l
Kruskal
Kruskal 算法都基于贪心算法的策略
最短路径:
Dijkstra算法不允许存在负权边
Floyed 不允许有带负权的回路
拓扑排序:
每个顶点只出现一次
顶点 A 在序列中排在顶点 B 的前面,则在图中不存在顶点 B 到顶点 A 的路径
拓扑排序的实现:
①从 AOV 网中选择一个没有前驱( 入度为 0 ) 的顶点并输出
②从网中删除该顶点和以它为起点的有向边
重复 ① 和 ② 直到当前的 AOV 网为空或当前网中不存在无前驱的顶点为止
关键路径