赞
踩
线性表:顺序表示+链式表示
一、根据数据元素之间分为4类基本结构:
(1)集合(2)线性结构(3)树形结构(4)图状结构或网状结构
typedef int Status;
二、双向链表中插入一个结点时指针的变化情况:
s -> prior = p -> prior;
p -> proir -> next = s;
s -> next = p;
p -> proir = s;
三、栈的应用:表达式求值
#include <iostream> #include <vector> #include <string> #include "ImprovedStack.h" int priority(char c) { int k; switch (c) { case '*':k = 2; break; case '/':k = 2; break; case '+':k = 1; break; case '-':k = 1; break; case '(':k = 0; break; case ')':k = 0; break; default:k = -1; break; } return k; } void processAndOperator(Stack<int>& operandStack,Stack<char>& operatorStack){ double result; int op1=operandStack.pop(); int op2=operandStack.pop(); switch(operatorStack.pop()){ case '+': result=op1+op2; cout<<op1<<"+"<<op2<<"="<<result<<endl; break; case '-': result=op2-op1; cout<<op2<<"-"<<op1<<"="<<result<<endl; break; case '*': result=op1*op2; cout<<op2<<"*"<<op1<<"="<<result<<endl; break; case '/': result=op2/op1; cout<<op2<<"/"<<op1<<"="<<result<<endl; break; default: break; } operandStack.push(result); } int evaluateExpression(const string& expression){ Stack<int> operandStack; Stack<char> operatorStack; int i=0,flag=1; while(flag){ char c=expression[i]; if(c>='0'&&c<='9') { operandStack.push(c-'0'); //cout<<"操作数入栈"<<c<<endl; i++; }else if((c=='+'||c=='-'||c=='*'||c=='/')&&operatorStack.empty()){ operatorStack.push(c); //cout<<"第一个操作符"<<c<<"入栈"<<endl; i++; } else if(c=='\0'&&operatorStack.peek()=='\0') { flag=0; } else if(c=='('||(priority(c)>priority(operatorStack.peek()))) { operatorStack.push(c); i++; } else if(c==')'&&operatorStack.peek()=='(') { operatorStack.pop(); i++; } else if(priority(c)<=priority(operatorStack.peek())) { processAndOperator(operandStack,operatorStack); } } return operandStack.pop(); } int main(){ string expression; cout<<"Enter an expression: "; while(getline(cin,expression)){ cout<<expression<<" = "<<evaluateExpression(expression)<<endl; cout<<"Enter an expression: "; } return 0; }
四、广义表
五、树和二叉树
六、二叉树的遍历
先序遍历:根,左子树,右子树
中序遍历:左子树,根,右子树
后序遍历:左子树,右子树,根
按层遍历:从根开始,依次向下,对于每一层从左向右遍历。
二叉树的非递归遍历:借助栈来实现
(1) 非递归先根遍历二叉树
void PreorderPrint(SearchBTree T) // 先序根(序)遍历二叉树并打印出结点值 { if (T == nullptr) { cout << "Empty tree!"; exit(1); } Stack S = new StackNode; // 借助栈来实现 initStack(S); TreeNode* pT = T; // 创建临时结点指向根节点 while (pT || !isEmpty(S)) // 当结点不为空或者栈不为空执行循环 { if (pT) // 当pT不为空 { Push(S, pT); // pT入栈 cout << pT->data << " "; // 打印当前结点 pT = pT->left; // pT移动指向其左孩子 } else { // pT为空,则获取栈顶元素,并出栈 pT = getTop(S); Pop(S); // 若pT为空表示左子树的左孩子全部遍历完,依次出栈 pT = pT->right; // 当左孩子及根结点遍历完之后,开始遍历其右子树 } } cout << endl; delete S; }
(2)非递归中根遍历二叉树
void InorderPrint(SearchBTree T) // 中根(序)遍历二叉树并打印出结点值 { if (T == nullptr) { cout << "Empty tree!"; exit(1); } Stack S = new StackNode; // 借助栈来实现 initStack(S); TreeNode* pT = T; // 创建临时结点指向根节点 while (pT || !isEmpty(S)) // 当结点不为空或者栈不为空执行循环 { if (pT) // 当pT不为空 { Push(S, pT); // pT入栈 pT = pT->left; // pT移动指向其左孩子 } else { // pT为空,则 pT = getTop(S); Pop(S); cout << pT->data << " "; // 若pT为空表示左子树的左孩子全部遍历完,依次出栈并打印 pT = pT->right; // 当左孩子及根结点遍历完之后,开始遍历其右子树 } } cout << endl; delete S; }
(3)非递归后根遍历二叉树
void PostorderPrint(SearchBTree T) // 先根(序)遍历二叉树并打印出结点值 { if (T == nullptr) { cout << "Empty tree!"; exit(1); } Stack S = new StackNode; // 借助栈来实现 initStack(S); TreeNode* pT = T; // 创建临时结点指向根节点 TreeNode* qT = nullptr; while (pT || !isEmpty(S)) // 当结点不为空或者栈不为空执行循环 { if (pT) // 当pT不为空 { Push(S, pT); // pT入栈 pT = pT->left; // pT移动指向其左孩子 } else { pT = getTop(S); // 取栈顶元素作为当前结点 if (pT->right && pT->right != qT) // 若当前节点有右孩子且不是上一次已经被访问的结点 { pT = pT->right; // 指向其右孩子 } else { // 若当前结点没有右孩子或者未被访问,则 Pop(S); // 出栈 cout << pT->data << " "; // 访问当前结点的数据 qT = pT; // 令pT记录当前结点,用于稍后判断是否已经被访问过 pT = nullptr; // 将当前结点赋值为空 } // 当左孩子及根结点遍历完之后,开始遍历其右子树 } } cout << endl; delete S; }
(4)按层遍历
public void levelTraverse(BinarySearchTree<T> tree){ levelTraverse(tree.root); } private void levelTraverse(BinaryNode<T> root){ if(root == null) return; Queue<BinaryNode<T>> queue = new LinkedList<>();//层序遍历时保存结点的队列 queue.offer(root);//初始化 while(!queue.isEmpty()){ BinaryNode<T> node = queue.poll();//获取对头元素并删除 System.out.print(node.element + " ");//访问节点 if(node.left != null) queue.offer(node.left); if(node.right != null) queue.offer(node.right); } }
七、森林与二叉树
森林中的每棵树先变成二叉树,然后再连接起来。
八、Huffman树及其应用
1.构造Huffman树: Huffman算法
(1)对权值进行排序,树的集合为F
(2)选择最小的两个权值作为左右子树构建一个新的二叉树,
根节点的权值是左右子树结点权值之和。
(3)删除这两棵树,将新生成的二叉树添加到F中。
(4)一直重复,(2)(3),直到F中只有一棵树为止。
Huffman编码:左0右1
WPL = 71 + 52 + 23 + 43 = 35
九、图
1.图的存储结构:邻接矩阵+邻接表
(1)邻接矩阵
(2)邻接表
(1)深度优先搜索DFS,类似于树的先根遍历。
深度优先搜索(DFS):v1 -> v2 -> v4 ->v8 -> v5 -> v3 -> v6 -> v7
(2)广度优先搜索(BFS),类似于树的按层遍历的过程
广度优先搜索(BFS)序列:v1 -> v2 -> v3 -> v4 -> v5 -> v6 -> v7 -> v8
3.最小生成树
构造连接网的最小代价生成树(简称为最小生成树)问题,一颗生成树的代价就是树上各边的代价之和。Prim算法+Kruskal算法
(1)Prim算法
(2)Kruskal算法
4.有向无环图及其应用
一个无环的有向图称为:有向无环图,简称DAG(directed acycline graph)图
应用:拓扑排序+关键路径
(1)拓扑排序
AOV网中的拓扑排序算法
(2)AOE中的关键路径
AOE网(activity on edge):边表示活动的网。AOE网是一个带权的有向无环图,其中,顶点表示事件,弧表示活动,权表示活动持续的事件。
路径长度最长的路径叫做关键路径。
5.最短路径问题 :迪杰斯特拉(DijKstra)算法
给定带权有向图G和源点v,求从v到G中其余各顶点的最短路径
(1)初始化时,S只含有源节点;
(2)从U中选取一个距离v最小的顶点k加入S中(该选定的距离就是v到k的最短路径长度);
(3)以k为新考虑的中间点,修改U中各顶点的距离;若从源节点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值是顶点k的距离加上k到u的距离;
(4)重复步骤(2)和(3),直到所有顶点都包含在S中。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。