PAT树_层序遍历叶节点、中序建树后序输出、AVL树的根、二叉树路径存在性判定、奇妙的完全二叉搜索树、最小堆路径、文件路由
03-树1. List Leaves (25)
Given a tree, you are supposed to list all the leaves in the order of top down, and left to right. Input Specification: Each input file contains one test case. For each case, the first line gives a positive integer N (<=10) which is the total number of nodes in the tree -- and hence the nodes are numbered from 0 to N-1. Then N lines follow, each corresponds to a node, and gives the indices of the left and right children of the node. If the child does not exist, a "-" will be put at the position. Any pair of children are separated by a space. Output Specification: For each test case, print in one line all the leaves' indices in the order of top down, and left to right. There must be exactly one space between any adjacent numbers, and no extra space at the end of the line. Sample Input:
8
1 -
- -
0 -
2 7
- -
- -
5 -
4 6
Sample Output:
4 1 5
/*
思路:需要动态的建立二叉树,然后层次遍历输出叶结点,但是有一个问题是要防止指针丢失,因此我在程序中用一个数组维护各个结点的指针;最后树建完以后,还要想办法找到数根,我采取的措施是:遍历维护结点指针的数组,对其左、右结点值求和,这样除了根结点以外,所有结点都被计入总和中了,利用这一信息便可以找到根节点的位置。
*/
#include<stdio.h>
#include<string.h>
#include<malloc.h>
#define MAXN 10 typedef struct tnode
{
int data;
struct tnode * left;
struct tnode * right;
}TNODE, *PTNODE; typedef struct qnode
{
PTNODE data;
struct qnode * next;
}QNODE, *PQNODE; typedef struct queue
{
PQNODE front;
PQNODE rear;
}QUEUE, *PQUEUE; PQUEUE MakeQueue();
void Add(PQUEUE, PTNODE pTNode);
PTNODE Delete(PQUEUE pQ);
int IsEmpty(PQUEUE pQ); PTNODE arr[MAXN+];
void Dispose(int i, char left, char right);
PTNODE FindRoot(int n); // n个节点中找根节点 int main(void)
{
int n, i, isFirst;
char left, right;
PTNODE root, head; scanf("%d", &n);
memset(arr, , sizeof(arr));
for(i = ; i < n; i++)
{
scanf(" %c %c", &left, &right);
Dispose(i, left, right);
} root = FindRoot(n);
// printf("%d\n", root->data); // test
// 层次遍历
PQUEUE pQ = MakeQueue();
Add(pQ, root);
isFirst = ;
while(!IsEmpty(pQ))
{
head = Delete(pQ);
if(head->left == NULL && head->right == NULL)
{
if(isFirst)
isFirst = ;
else
putchar(' '); printf("%d", head->data);
} Add(pQ, head->left);
Add(pQ, head->right);
} return ;
} void Dispose(int i, char left, char right) // 当前节点,左、右节点哪个没有建哪个
{
if(arr[i] == NULL)
arr[i] = (PTNODE)malloc(sizeof(TNODE));
arr[i]->data = i; if(left == '-')
arr[i]->left = NULL;
else
{
if(arr[left-''] == NULL)
arr[left-''] = (PTNODE)malloc(sizeof(TNODE));
arr[i]->left = arr[left-''];
} if(right == '-')
arr[i]->right = NULL;
else
{
if(arr[right-''] == NULL)
arr[right-''] = (PTNODE)malloc(sizeof(TNODE));
arr[i]->right = arr[right-''];
} return; } PTNODE FindRoot(int n)
{
int i, sum = ; for(i = ; i < n; i++)
{
if(arr[i]->left)
sum += arr[i]->left->data;
if(arr[i]->right)
sum += arr[i]->right->data;
} return arr[n*(n-)/ - sum]; // 这里用了一点技巧
} PQUEUE MakeQueue()
{
PQUEUE pQ = malloc(sizeof(QUEUE));
pQ->front = pQ->rear = NULL; return pQ;
} void Add(PQUEUE pQ, PTNODE pTNode)
{
if(pTNode == NULL)
return; PQNODE p = (PQNODE)malloc(sizeof(QNODE)); // 注意正规的程序应该检查申请堆内存是否成功
p->data = pTNode;
p->next = NULL; if(pQ->front == NULL)
pQ->front = pQ->rear = p;
else
{
pQ->rear->next = p;
pQ->rear = p;
}
} PTNODE Delete(PQUEUE pQ)
{
PTNODE p;
PQNODE pTemp; if(pQ->front == NULL)
return NULL;
if(pQ->rear == pQ->front)
pQ->rear = NULL; p = pQ->front->data; pTemp = pQ->front;
pQ->front = pQ->front->next;
free(pTemp); return p;
} int IsEmpty(PQUEUE pQ)
{
return pQ->front == NULL ? : ;
}
03-树2. Tree Traversals Again (25)
An inorder binary tree traversal can be implemented in a non-recursive way with a stack. For example, suppose that when a 6-node binary tree (with the keys numbered from 1 to 6) is traversed, the stack operations are: push(1); push(2); push(3); pop(); pop(); push(4); pop(); pop(); push(5); push(6); pop(); pop(). Then a unique binary tree (shown in Figure 1) can be generated from this sequence of operations. Your task is to give the postorder traversal sequence of this tree.
Input Specification: Each input file contains one test case. For each case, the first line contains a positive integer N (<=30) which is the total number of nodes in a tree (and hence the nodes are numbered from 1 to N). Then 2N lines follow, each describes a stack operation in the format: "Push X" where X is the index of the node being pushed onto the stack; or "Pop" meaning to pop one node from the stack. Output Specification: For each test case, print the postorder traversal sequence of the corresponding tree in one line. A solution is guaranteed to exist. All the numbers must be separated by exactly one space, and there must be no extra space at the end of the line. Sample Input:
6
Push 1
Push 2
Push 3
Pop
Pop
Push 4
Pop
Pop
Push 5
Push 6
Pop
Pop
Sample Output:
3 4 2 6 5 1
/*
思路:先用一个真实的栈模拟输入,据此中序建树,然后执行后序遍历输出结果即可
*/
#include<stdio.h>
#include<malloc.h>
typedef struct tnode
{
int data;
struct tnode * left;
struct tnode * right;
}TNODE, *PTNODE; typedef struct snode
{
PTNODE data;
struct snode * next;
}SNODE, *PSNODE; PSNODE MakeStack();
void Push(PSNODE * pS, PTNODE data);
PTNODE Pop(PSNODE * pS);
int IsEmpty(PSNODE pS); PTNODE Dispose(PTNODE * lastPTNode, int numberNode);
void PostOrderTraverse(PTNODE pTNode); int first = ; // 后序遍历中是否是第一个输出节点的标记 int main(void)
{
int n, numberNode;
PTNODE root, lastPTNode, currentPTNode;
PSNODE pS;
char str[]; pS = MakeStack(); scanf("%d", &n);
scanf("%s%d", str, &numberNode);
// 建立数根root,并将之压栈
root = lastPTNode = (PTNODE)malloc(sizeof(TNODE));
root->data = numberNode;
root->left = root->right = NULL;
Push(&pS, root); while(scanf("%s", str) != EOF)
{
if(str[] == 'u')
{
scanf("%d", &numberNode);
currentPTNode = Dispose(&lastPTNode, numberNode);
Push(&pS, currentPTNode);
}
else if(str[] == 'o')
{
lastPTNode = Pop(&pS);
}
} PostOrderTraverse(root); return ;
} PSNODE MakeStack()
{
PSNODE p = (PSNODE)malloc(sizeof(SNODE));
p->data = NULL; return p;
}
void Push(PSNODE * pS, PTNODE data)
{
PSNODE p = (PSNODE)malloc(sizeof(SNODE)); p->data = data;
p->next = *pS;
*pS = p;
}
PTNODE Pop(PSNODE * pS)
{
PTNODE data;
PSNODE pTemp;
if(IsEmpty(*pS))
return NULL; data = (*pS)->data; // 优先级!
pTemp = *pS;
*pS = (*pS)->next;
free(pTemp); return data;
} int IsEmpty(PSNODE pS)
{
return pS == NULL ? : ;
} PTNODE Dispose(PTNODE * lastPTNode, int numberNode)
{
PTNODE pTemp; pTemp = (PTNODE)malloc(sizeof(TNODE));
pTemp->data = numberNode;
pTemp->left = pTemp->right = NULL;
if((*lastPTNode)->left == NULL) // 注意运算符优先级
(*lastPTNode)->left = pTemp;
else
(*lastPTNode)->right = pTemp; *lastPTNode = pTemp; return pTemp;
} void PostOrderTraverse(PTNODE pTNode)
{
if(pTNode)
{ PostOrderTraverse(pTNode->left);
PostOrderTraverse(pTNode->right);
if(first)
first = ;
else
putchar(' ');
printf("%d", pTNode->data);
} return ;
}
04-树3. Root of AVL Tree (25)
An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Figures 1-4 illustrate the rotation rules.
Now given a sequence of insertions, you are supposed to tell the root of the resulting AVL tree. Input Specification: Each input file contains one test case. For each case, the first line contains a positive integer N (<=20) which is the total number of keys to be inserted. Then N distinct integer keys are given in the next line. All the numbers in a line are separated by a space. Output Specification: For each test case, print ythe root of the resulting AVL tree in one line. Sample Input 1:
5
88 70 61 96 120
Sample Output 1:
70
Sample Input 2:
7
88 70 61 96 120 90 65
Sample Output 2:
88
// 很直白的考察AVL建树,不过多赘述了~
#include<stdio.h>
#include<malloc.h>
typedef struct node
{
int data;
struct node * left;
struct node * right;
int height;
}NODE, *PNODE;
PNODE Insert(PNODE pNode, int data);
int Height(PNODE pNode);
int MaxHeight(PNODE pLeft, PNODE pRight);
PNODE SingleRightRotation(PNODE A);
PNODE DoubleRightLeftRotation(PNODE A);
PNODE SingleLeftRotation(PNODE A);
PNODE DoubleLeftRightRotation(PNODE A);
int main(void)
{
int n, data;
PNODE avlRoot; scanf("%d", &n);
scanf("%d", &data);
avlRoot = Insert(NULL, data);
n--;
while(n--)
{
scanf("%d", &data);
avlRoot = Insert(avlRoot, data);
} printf("%d\n", avlRoot->data);
return ;
} PNODE Insert(PNODE pRoot, int data)
{
if(pRoot == NULL)
{
pRoot = (PNODE)malloc(sizeof(NODE));
pRoot->data = data;
pRoot->left = pRoot->right = NULL;
pRoot->height = ;
}
else if(data > pRoot->data)
{
pRoot->right = Insert(pRoot->right, data);
// 判断是否要旋转
if(Height(pRoot->right) - Height(pRoot->left) == )
{
// 判断是右右旋转还是右左旋转
if(data > pRoot->right->data) // 右右旋转
return SingleRightRotation(pRoot); // 旋转完了返回修正部分的根节点,并将其返回给上一次调用它的父节点
else // 右左旋转
return DoubleRightLeftRotation(pRoot);
} }
else if(data < pRoot->data)
{
pRoot->left = Insert(pRoot->left, data);
if(Height(pRoot->left) - Height(pRoot->right) == )
{
if(data < pRoot->left->data) // 左左旋转
return SingleLeftRotation(pRoot);
else // 左右旋转
return DoubleLeftRightRotation(pRoot); }
} pRoot->height = MaxHeight(pRoot->left, pRoot->right) + ; return pRoot;
} int Height(PNODE pNode)
{
if(pNode == NULL)
return -;
else
return pNode->height;
} int MaxHeight(PNODE pLeft, PNODE pRight)
{
if(pLeft == NULL && pRight == NULL)
return -;
else if(pLeft == NULL)
return pRight->height;
else if(pRight == NULL)
return pLeft->height;
else if(pLeft->height > pRight->height)
return pLeft->height;
else
return pRight->height;
} PNODE SingleRightRotation(PNODE A) // 右右旋转,返回旋转部分的根节点
{
PNODE B = A->right;
A->right = B->left;
B->left = A; /* 可以代替下面两行:
A->height = Height(A->left) + 1; // 这里没有通过比较更新A的高度,因为我觉得其高度不会变,因为BL不会大于AL(否则在之前它们就不平衡了),更具体的原因可以在我之前的博文"AVL树旋转特性"中找到
B->height = A->height + 1; // 与上述理由类似
*/ A->height = MaxHeight(A->left, A->right) + ;
B->height = MaxHeight(B->left, A) + ; return B;
} PNODE DoubleRightLeftRotation(PNODE A)
{
// 注意到只需要左左旋转然后右右旋转,两者组合起来就是右左旋转
A->right = SingleLeftRotation(A->right); // 以B为根进行左左旋转
return SingleRightRotation(A); // 以A为根进行右右旋转
} PNODE SingleLeftRotation(PNODE A)
{
PNODE B = A->left;
A->left = B->right;
B->right = A; A->height = MaxHeight(A->left, A->right) + ;
B->height = MaxHeight(B->left, A) + ; return B;
} PNODE DoubleLeftRightRotation(PNODE A)
{
A->left = SingleRightRotation(A->left);
return SingleLeftRotation(A);
}
04-树4. Search in a Binary Search Tree (25)
To search a key in a binary search tree, we start from the root and move all the way down, choosing branches according to the comparison results of the keys. The searching path corresponds to a sequence of keys. For example, following {1, 4, 2, 3} we can find 3 from a binary search tree with 1 as its root. But {2, 4, 1, 3} is not such a path since 1 is in the right subtree of the root 2, which breaks the rule for a binary search tree. Now given a sequence of keys, you are supposed to tell whether or not it indeed correspnds to a searching path in a binary search tree. Input Specification: Each input file contains one test case. For each case, the first line gives two positive integers N and M (<=100) which are the total number of sequences, and the size of each sequence, respectively. Then N lines follow, each gives a sequence of keys. It is assumed that the keys are numbered from 1 to M. Output Specification: For each sequence, print in a line "YES" if the sequence does correspnd to a searching path in a binary search tree, or "NO" if not. Sample Input:
3 4
1 4 2 3
2 4 1 3
3 2 4 1
Sample Output:
YES
NO
NO
/*
思路:按照给定的数据建树,只要当前结点是上一个节点的孩子,则继续这个过程,如果到达输入末尾,则说明路径存在,否则路径不存在,PS:由于这个思路执行起来更快,所以选择了它,其实解决这个问题的时候,我首先想到的办法是:根据输入建树,然后最后输入的那个结点,如果查找的过程中经过了所有结点,那么路径存在,否则路径不存在
*/
#include<stdio.h>
#include<malloc.h>
typedef struct node
{
int data;
struct node * left;
struct node * right;
}NODE, *PNODE; PNODE Insert(PNODE root, int data); // 返回插入的节点,如果节点已经存在,返回空指针
PNODE Find(PNODE root, int data);
void Delete(PNODE root);
int main(void)
{
int flag; // 当前节点是否是上一个节点的孩子的标记变量
PNODE curNode, preNode, root;
int i, n, m, data; scanf("%d%d", &n, &m);
root = NULL;
while(n--)
{
Delete(root); // 删除上一次建的树
scanf("%d", &data);
root = NULL; // 注意一定要置空,否则用上次释放的root做根会出现访问非法的问题
root = Insert(root, data); // 首先建立根节点
preNode = root;
flag = ;
for(i = ; i < m; i++)
{
scanf("%d", &data);
if(flag)
{
Insert(root, data);
curNode = Find(root, data);
if(preNode->left != curNode && preNode->right != curNode)
flag = ; preNode = curNode;
}
}
if(flag)
printf("YES\n");
else
printf("NO\n");
} return ;
} PNODE Insert(PNODE root, int data)
{
if(root == NULL)
{
PNODE pNode = (PNODE)malloc(sizeof(NODE));
pNode->data = data;
pNode->left = pNode->right = NULL;
return pNode;
} if(data > root->data)
root->right = Insert(root->right, data); // 由于插入的时候需要记住它的父节点,因此这里有赋值语句
else if(data < root->data)
root->left = Insert(root->left, data);
else // 数据相等的话直接退出,因为二叉搜索树不允许有相同的键值
return NULL; return root;
} PNODE Find(PNODE root, int data)
{
if(root == NULL)
return NULL;
if(data > root->data)
return Find(root->right, data);
else if(data < root->data)
return Find(root->left, data);
else
return root;
} void Delete(PNODE root)
{
if(root == NULL)
return ; Delete(root->right); // 删除右子树
root->right = NULL; // 注意到这里需要赋值语句用来修改节点的右指针 Delete(root->left);
root->left = NULL; free(root); // 释放根节点的空间
}
04-树5. Complete Binary Search Tree (30)
A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties: The left subtree of a node contains only nodes with keys less than the node's key.
The right subtree of a node contains only nodes with keys greater than or equal to the node's key.
Both the left and right subtrees must also be binary search trees.
A Complete Binary Tree (CBT) is a tree that is completely filled, with the possible exception of the bottom level, which is filled from left to right. Now given a sequence of distinct non-negative integer keys, a unique BST can be constructed if it is required that the tree must also be a CBT. You are supposed to output the level order traversal sequence of this BST. Input Specification: Each input file contains one test case. For each case, the first line contains a positive integer N (<=1000). Then N distinct non-negative integer keys are given in the next line. All the numbers in a line are separated by a space and are no greater than 2000. Output Specification: For each test case, print in one line the level order traversal sequence of the corresponding complete binary search tree. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line. Sample Input:
10
1 2 3 4 5 6 7 8 9 0
Sample Output:
6 3 8 1 5 7 9 0 2 4
/*
首先,这个题真的很有意思:~
思路: 把输入数据放入数组冒泡排序
用类似层次遍历的方式建立一颗有N个节点的完全二叉树,每次malloc一个节点num加一
采用中序遍历的方式用一个全局变量将所用的节点标号
层次遍历,根据标号(对应数组下标)放入数值(为了更好的达到练习效果,我直接先序了),同时输出
*/
#include<stdio.h>
#include<malloc.h>
#define MAXN 1000
int Arr[MAXN + ];
int G_NUM; // 定义成全局变量方便创建完全二叉树
int G_COUNT = ; // 记录已经创建的树的节点的个数
int G_NUMBER = ; // 节点标号,左-中-右依次递增
void BbSort(int Arr[], int n); typedef struct TNode
{
int data;
struct TNode * left;
struct TNode * right;
}TNODE, *PTNODE; typedef struct QNode
{
PTNODE data;
struct QNode * next;
}QNODE, *PQNODE;
// 树操作
PTNODE CreateCBT();
void LevelOrderTraversal(PTNODE pRoot); // 用层次遍历的方式建立完全二叉树
void InOrderTraversal(PTNODE pRoot); // 用中序遍历的方式给节点编号
void PreOrderTraversal(PTNODE pRoot); // 用先序遍历的方式给节点赋值
void LevelOrderTraversal2(PTNODE pRoot); // 输出层次遍历结果
typedef struct Queue
{
PQNODE front;
PQNODE rear;
}QUEUE, *PQUEUE; // 队列操作
PQUEUE CreatQueue();
void EnQueue(PQUEUE pQueue, PTNODE pTNode);
PTNODE DeQueue(PQUEUE pQueue);
int IsEmpty(PQUEUE pQueue); int main(void)
{
int i;
PTNODE pRoot; scanf("%d", &G_NUM);
for(i = ; i < G_NUM; i++)
scanf("%d", &Arr[i]);
BbSort(Arr, G_NUM); pRoot = CreateCBT();
LevelOrderTraversal(pRoot); // 层次遍历的方式建立完全二叉树 InOrderTraversal(pRoot); // 中序遍历标号 // 下面两行代码其实可以用一个层次遍历来代替, 就是给节点赋值的同时输出该值,当然按照AC的角度理解的话,可以不用赋值直接输出
PreOrderTraversal(pRoot); // 先序遍历给节点赋值 LevelOrderTraversal2(pRoot); // 层次遍历的同时输出节点的值 return ;
} void BbSort(int Arr[], int n)
{
int temp, outer, inner, flag; flag = ;
for(outer = n-; outer > && flag; outer--)
{
flag = ;
for(inner = ; inner < outer; inner++)
{
if(Arr[inner] > Arr[inner+])
{
temp = Arr[inner];
Arr[inner] = Arr[inner+];
Arr[inner+] = temp;
flag = ;
}
}
}
} PTNODE CreateCBT()
{
if(G_COUNT == G_NUM)
return NULL; PTNODE root = (PTNODE)malloc(sizeof(TNODE));
root->left = root->right = NULL;
G_COUNT++;
return root;
} void LevelOrderTraversal(PTNODE pRoot)
{
PTNODE pTNode;
PQUEUE pQueue = CreatQueue();
EnQueue(pQueue, pRoot);
while(!IsEmpty(pQueue))
{
pTNode = DeQueue(pQueue);
pTNode->left = CreateCBT();
pTNode->right = CreateCBT();
EnQueue(pQueue, pTNode->left);
EnQueue(pQueue, pTNode->right);
}
} void LevelOrderTraversal2(PTNODE pRoot)
{
int flag = ;
PTNODE pTNode;
PQUEUE pQueue = CreatQueue();
EnQueue(pQueue, pRoot);
while(!IsEmpty(pQueue))
{
pTNode = DeQueue(pQueue);
if(flag)
putchar(' ');
else
flag = ;
printf("%d", pTNode->data);
EnQueue(pQueue, pTNode->left);
EnQueue(pQueue, pTNode->right);
}
} void InOrderTraversal(PTNODE pRoot)
{
if(pRoot)
{
InOrderTraversal(pRoot->left);
pRoot->data = G_NUMBER;
G_NUMBER++;
InOrderTraversal(pRoot->right);
}
}
void PreOrderTraversal(PTNODE pRoot)
{
if(pRoot)
{
pRoot->data = Arr[pRoot->data];
PreOrderTraversal(pRoot->left);
PreOrderTraversal(pRoot->right);
}
}
PQUEUE CreatQueue()
{
PQUEUE pQ = (PQUEUE)malloc(sizeof(QUEUE));
pQ->front = pQ->rear = NULL;
return pQ;
} void EnQueue(PQUEUE pQueue, PTNODE pTNode)
{
if(pTNode == NULL)
return;
PQNODE pQNode= (PQNODE)malloc(sizeof(QNODE));
pQNode->data = pTNode;
pQNode->next = NULL; if(pQueue->front == NULL)
pQueue->front = pQueue->rear = pQNode;
else
{
pQueue->rear->next = pQNode;
pQueue->rear = pQNode;
}
} PTNODE DeQueue(PQUEUE pQueue)
{
PTNODE pTNode; if(pQueue->front == NULL)
return NULL;
if(pQueue->rear == pQueue->front)
pQueue->rear = NULL; PQNODE pQNode = pQueue->front;
pQueue->front = pQueue->front->next;
pTNode = pQNode->data;
free(pQNode);
return pTNode;
} int IsEmpty(PQUEUE pQueue)
{
if(pQueue->front == NULL)
return ;
else
return ;
}
05-树6. Path in a Heap (25)
Insert a sequence of given numbers into an initially empty min-heap H. Then for any given index i, you are supposed to print the path from H[i] to the root. Input Specification: Each input file contains one test case. For each case, the first line gives two positive integers N and M (<=1000) which are the size of the input sequence, and the number of indices to be checked, respectively. Given in the next line are the N integers in [-10000, 10000] which are supposed to be inserted into an initially empty min-heap. Finally in the last line, M indices are given. Output Specification: For each index i in the input, print in one line the numbers visited along the path from H[i] to the root of the heap. The numbers are separated by a space, and there must be no extra space at the end of the line. Sample Input:
5 3
46 23 26 24 10
5 4 3
Sample Output:
24 23 10
46 23 10
26 10
/*
考察堆的基本操作
*/
#include<stdio.h> // 堆常见的操作有Creat、Insert、Delete、IsFull、IsEmpty这里只关心AC,因此省略了不相干操作的实现
#include<malloc.h>
#define CAPACITY 1000 // 堆的最大容量
#define MIN -10001 // 堆数组中下标为0的元素-哨兵的应赋予的初值
typedef struct Heap
{
int * arr;
int size; // 当前元素的个数
int capacity; // 最大容量
}HEAP, *PHEAP;
PHEAP CreateHeap(int capacity);
void Insert(PHEAP pHeap, int data);
void PrintPath(PHEAP pHeap, int i); // 从下标为i的位置开始打印其父节点的值,直到到达数根为止
int main(void)
{
int n, m, data, i;
PHEAP pHeap; scanf("%d%d", &n, &m);
pHeap = CreateHeap(CAPACITY);
while(n--)
{
scanf("%d", &data);
Insert(pHeap, data);
}
while(m--)
{
scanf("%d", &i);
PrintPath(pHeap, i);
printf("\n");
} return ;
} PHEAP CreateHeap(int capacity)
{
PHEAP pHeap = (PHEAP)malloc(sizeof(HEAP));
pHeap->arr = (int *)malloc(sizeof(int) * (capacity+));
pHeap->arr[] = MIN; // arr[0]做哨兵,方便查找操作
pHeap->size = ;
pHeap->capacity =capacity; return pHeap;
} void Insert(PHEAP pHeap, int data)
{
int position = ++pHeap->size; // 应该先判堆是否满的,因为测试数据不会导致堆满,因此判断堆是否满的操作省略了 for(; data < pHeap->arr[position/]; position /= )
pHeap->arr[position] = pHeap->arr[position/]; // 向下(数根)过滤节点 pHeap->arr[position] = data;
} void PrintPath(PHEAP pHeap, int i) // 从下标为i的位置开始打印其父节点的值,直到到达数根为止
{
int isFirst = ;
while(i)
{
if(isFirst)
isFirst = ;
else
printf(" ");
printf("%d", pHeap->arr[i]);
i /= ;
}
}
05-树7. File Transfer (25)
We have a network of computers and a list of bi-directional connections. Each of these connections allows a file transfer from one computer to another. Is it possible to send a file from any computer on the network to any other? Input Specification: Each input file contains one test case. For each test case, the first line contains N (2<=N<=104), the total number of computers in a network. Each computer in the network is then represented by a positive integer between 1 and N. Then in the following lines, the input is given in the format: I c1 c2
where I stands for inputting a connection between c1 and c2; or C c1 c2
where C stands for checking if it is possible to transfer files between c1 and c2; or S
where S stands for stopping this case. Output Specification: For each C case, print in one line the word "yes" or "no" if it is possible or impossible to transfer files between c1 and c2, respectively. At the end of each case, print in one line "The network is connected." if there is a path between any pair of computers; or "There are k components." where k is the number of connected components in this network. Sample Input 1:
5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
S
Sample Output 1:
no
no
yes
There are 2 components.
Sample Input 2:
5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
I 1 3
C 1 5
S
Sample Output 2:
no
no
yes
yes
The network is connected.
/*
写的这个代码有点自注释的感觉了,因此不写思路,它们都藏在我的代码里:~
*/
#include<stdio.h> // 经测试,路径压缩和高度差合并两个任取一个实现之就能AC,但是毫无疑问,两者皆实现能够保证最快的速度因而更保险
#include<string.h>
#define MAXN 10000
typedef struct set
{
int data;
int parent; // 采用数组下标的方式指示它的父节点
}SET; SET set[MAXN+]; // 方便起见,0号单元空着了,每个集合的根节点的parent置为一个负数 int Find(SET set[], int element); // 查找元素属于哪个集合,返回元素所在集合的根,未找到则返回-1
void Union(SET set[], int element1, int element2); // 将两个元素合并到一个集合中,方便起见,元素值放到对应下标中
int SetCount(SET set[], int n); // 统计n个元素构成的集合总数 int main(void)
{
int n, element1, element2, setCount;
char ch; memset(set, , sizeof(set));
scanf("%d", &n);
while(scanf(" %c", &ch) && ch != 'S')
{
scanf("%d%d", &element1, &element2);
if(ch == 'C')
{
if(Find(set, element1) != - && Find(set, element1) == Find(set, element2))
printf("yes\n");
else
printf("no\n");
}
else
Union(set, element1, element2);
} setCount = SetCount(set, n);
if(setCount == )
printf("The network is connected.\n");
else
printf("There are %d components.\n", setCount); return ;
} int Find(SET set[], int element)
{
int root = element;
int higher; if(set[element].data != element) // 因为set数组初始为0,而给定的最小输入是2,因此元素不在集合中的话,这个条件成立
return -; // for(; set[element].parent > 0; element = set[element].parent) // 没有路径压缩,直接超时
// ;
// return element; for(; set[root].parent > ; root = set[root].parent)
;
while(set[element].parent > )
{
higher = set[element].parent;
set[element].parent = root;
element = higher;
} return root;
} void Union(SET set[], int element1, int element2) // 高度小的树并到高度大的树上,|parent|代表树的高度
{
int root1, root2; if(Find(set, element1) == -) // 如果元素不在集合中,则将其单独构成一个只包含其本身的集合
{
set[element1].data = element1; // 注意本行代码和下一行代码的顺序
set[element1].parent = -;
}
if(Find(set, element2) == -)
{
set[element2].data = element2;
set[element2].parent = -;
} root1 = Find(set, element1);
root2 = Find(set, element2);
if(root1 != root2)
{ if(set[root1].parent < set[root2].parent) // 如果root1的高度高,就把root2挂到root1上,
{
set[root2].parent = root1;
set[root1].parent -= ;
}
else
{
set[root1].parent = root2;
set[root2].parent -= ; } // set[root2].parent = root1; //没有高度控制的代码,在if(root1 != root2)里仅此一行 } return;
} int SetCount(SET set[], int n)
{
int i, count; count = ;
for(i = ; i <= n; i++)
{
if(set[i].parent <= ) // 小于零的元素代表添加到集合中的一个根,等于零的元素代表未添加到集合中的元素,它独自构成一个集合
count++;
} return count;
}
(XP_JIANG)
PAT树_层序遍历叶节点、中序建树后序输出、AVL树的根、二叉树路径存在性判定、奇妙的完全二叉搜索树、最小堆路径、文件路由的更多相关文章
- [LeetCode]105. 从前序与中序遍历序列构造二叉树(递归)、108. 将有序数组转换为二叉搜索树(递归、二分)
题目 05. 从前序与中序遍历序列构造二叉树 根据一棵树的前序遍历与中序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 题解 使用HashMap记录当前子树根节点在中序遍历中的位置,方便每次 ...
- 数据结构学习笔记_树(二叉搜索树,B-树,B+树,B*树)
一.查找二叉树(二叉搜索树BST) 1.查找二叉树的性质 1).所有非叶子结点至多拥有两个儿子(Left和Right): 2).所有结点存储一个关键字: 3).非叶子结点的左指针指向小于其关键字的子树 ...
- PAT 1043 Is It a Binary Search Tree (25分) 由前序遍历得到二叉搜索树的后序遍历
题目 A Binary Search Tree (BST) is recursively defined as a binary tree which has the following proper ...
- PAT L2-004. 这是二叉搜索树吗?【前序遍历转化为后序遍历】
一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点, 其左子树中所有结点的键值小于该结点的键值: 其右子树中所有结点的键值大于等于该结点的键值: 其左右子树都是二叉搜索树. 所谓二叉搜索 ...
- 树(二叉树 & 二叉搜索树 & 哈夫曼树 & 字典树)
树:n(n>=0)个节点的有限集.有且只有一个root,子树的个数没有限制但互不相交.结点拥有的子树个数就是该结点的度(Degree).度为0的是叶结点,除根结点和叶结点,其他的是内部结点.结点 ...
- 二叉搜索树、AVL平衡二叉搜索树、红黑树、多路查找树
1.二叉搜索树 1.1定义 是一棵二叉树,每个节点一定大于等于其左子树中每一个节点,小于等于其右子树每一个节点 1.2插入节点 从根节点开始向下找到合适的位置插入成为叶子结点即可:在向下遍历时,如果要 ...
- 剑指Offer面试题:22.二叉搜索树的后序遍历序列
一.题目:二叉搜索树的后序遍历序列 题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true,否则返回false.假设输入的数组的任意两个数字都互不相同. 例如在下面 ...
- (PAT)L2-004 这是二叉搜索树吗?(数据结构)
题目链接:https://www.patest.cn/contests/gplt/L2-004 一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点, 其左子树中所有结点的键值小于该结点的 ...
- PAT天梯赛L2-004 这是二叉搜索树吗【递归】
L2-004. 这是二叉搜索树吗? 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 一棵二叉搜索树可被递归地定义为具有下列性质的 ...
随机推荐
- 数据结构之KMP算法next数组
我们要找到一个短字符串(模式串)在另一个长字符串(原始串)中的起始位置,也就是模式匹配,最关键的是找到next数组.最简单的算法就是用双层循环来解决,但是这种算法效率低,kmp算法是针对模式串自身的特 ...
- 重置按钮小tip—为何不能重置表单数据呢
刚开始学html的同志有时候可能会遇到一个问题,就是为什么在编辑页面里面的重置按钮总是不起作用呢不清空数据呢?接下来就说明一下原因. Reset 对象 Reset 对象代表 HTML 表单中的一个重置 ...
- hihoCoder1388 Periodic Signal(2016北京网赛F:NTT)
题目 Source http://hihocoder.com/problemset/problem/1388 Description Profess X is an expert in signal ...
- css input[type=file] 样式美化,input上传按钮美化
css input[type=file] 样式美化,input上传按钮美化 参考:http://www.haorooms.com/post/css_input_uploadmh
- 2016最新 wamp2.5+windows 10安装CoedSgniffer代码格式检查:5分钟安装 30分钟入门和浏览常用命令
14:59 2016/1/112016最新 wamp2.5+windows 10安装CoedSgniffer代码格式检查:注意问题:1.手动安装2.5.0和pear安装方式都成功但是执行时无任何反映, ...
- Unity3d与Android交互
先看下效果 你一定会说,然并卵! 没错,这里只是一个最简单的例子,unity与android activity 互相传参数. 玩过手游的都知道,在你要为你心爱的游戏角色准备花钱买钻石,点击购买的时候, ...
- 一些关于Viewport与device-width的东西~
进行移动web开发已经有一年多的时间了,期间遇到了一些令人很困惑的东西.比如: 我们经常使用的<meta name="viewport" content="widt ...
- [Android]关于Installation error: INSTALL_PARSE_FAILED_MANIFEST_MALFORMED ,修改包名
查了很多,说修改manifest.本来是没有任何的修改,自动生成的,最后发现参考了人家的一篇: http://bbs.csdn.net/topics/390613702 修改包名,包名带了大些的开头了 ...
- SQL Server中的事物
1.事务的四个属性 原子性Atomicity,一致性Consistency,隔离性Isolation,持久性Durability ,即ACID特性. 原子性:事务必须是一个完整工作的单元,要么全部执行 ...
- JavaScript简单的tabel切换2
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...