老师 院长:对于基本的算法不用想,直接写出来。
在使用这些算法些别的算法。。。
B 数据结构:
逻辑结构 4中 : 集合 线性表 、树 图
物理结构2种: 顺序存储 链式存储
---
C语言基础中:
1: 顺序
2: if 判断
3: for 循环
2个搞定所有的(递归 迭代 队列)
-----------------------------折半查找 ----
- int bin_search(int x,int a[],int n){
- int low,high,mid;
- low = 0;
- high = n - 1;
- while(low <= high){
- mid = (low + high) / 2;
- if(x < a[mid]){
- high = mid - 1;
- }
- else if(x > a[mid]){
- low = mid + 1;
- }
- else{
- return mid;
- }
- }
- return -1;
- }
- //递归法
- int IterBiSearch(int data[], const int x, int beg, int last)
- {
- int mid = -1;
- mid = (beg + last) / 2;
- if (x == data[mid])
- {
- return mid;
- }
- else if (x < data[mid])
- {
- return IterBiSearch(data, x, beg, mid - 1);
- }
- else if (x > data[mid])
- {
- return IterBiSearch(data, x, mid + 1, last);
- }
- return -1;
- }
-------------------------快速排序------------
快速排序由于排序效率在同为O(N*logN)的几种排序方法中效率较高,因此经常被采用,再加上快速排序思想----分治法也确实实用
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
72 | 6 | 57 | 88 | 60 | 42 | 83 | 73 | 48 | 85 |
照着这个总结很容易实现挖坑填数的代码:
int AdjustArray(int s[], int l, int r) //返回调整后基准数的位置
{
int i = l, j = r;
int x = s[l]; //s[l]即s[i]就是第一个坑
while (i < j)
{
// 从右向左找小于x的数来填s[i]
while(i < j && s[j] >= x)
j--;
if(i < j)
{
s[i] = s[j]; //将s[j]填到s[i]中,s[j]就形成了一个新的坑
i++;
}
// 从左向右找大于或等于x的数来填s[j]
while(i < j && s[i] < x)
i++;
if(i < j)
{
s[j] = s[i]; //将s[i]填到s[j]中,s[i]就形成了一个新的坑
j--;
}
}
//退出时,i等于j。将x填到这个坑中。
s[i] = x;
return i;
}
再写分治法的代码:
void quick_sort1(int s[], int l, int r)
{
if (l < r)
{
int i = AdjustArray(s, l, r);//先成挖坑填数法调整s[]
quick_sort1(s, l, i - 1); // 递归调用
quick_sort1(s, i + 1, r);
}
}
这样的代码显然不够简洁,对其组合整理下:
---------------------------- 二叉树--------------二叉树的存储结构一般采用二叉链表,树中每一个结点都有一个数据域data还有两个分别用于指向该节点的左右儿子结点的指针域,通过这两个指针域建立了上下层结点的关系,这样就可以为以后的遍历奠定基础了。
- class BT_Node//二叉树结点类
- {
- public:
- T data;//结点类 数据域
- BT_Node<T> *leftchild;//用于指向左孩子的指针域
- BT_Node<T> *rightchild;//用于指向右孩子的指针域
- if(item != endflag_value)
- {
- subTree = new BT_Node<T>(item);//调用含参 构造函数 指针域为NULL
- if(subTree == NULL)
- {
- cout<<"内存分配错误!"<<endl;
- exit(1);//强制结束进程
- }
- CreateBinTree_(in,subTree->leftchild);//递归调用 建立当前结点为根结点的左右子树
- CreateBinTree_(in,subTree->rightchild);
- }
二叉树的遍历 与popStar中Matrix的遍历区别为啥如此大:
for(i=1;i<=ROW; i++){ for(j=1;j<=COL;j++) { clean } } --- 生产 同色 同行 。。。
void PreOrder(BTNode<T>* p, void (*visit)(T &data))
{
if (p){ visit(p->data);
PreOrder(p->left, visit); PreOrder(p->right, visit); }
}
递归: 后调用的先执行 栈 循环 递归 迭代
while(l) -- right 链表的遍历
{
l=l->next;
printf()
}
-------根本原因是在内存中储存的树是非线性结构
递归编辑
分治算法
2二分法
利用分治策略求解时,所需时间取决于分解后子问题的个数、子问题的规模大小等因素,而二分法,由于其划分的简单和均匀的特点,是经常采用的一种有效的方法,例如二分法检索
(1)分解,将要解决的问题划分成若干规模较小的同类问题;
(2)求解,当子问题划分得足够小时,用较简单的方法解决;
(3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。
折半查找 分治法。分治法是将大规模问题以同样的方式不断地分解为小规模问题,通过小规模问题的解决最终解决整个问题。而折半查找没进行一次,都会将一半规模问题抛掉。
( 8)最接近点对问题
用贪心法求解背包问题的关键是如何选定贪心策略,使得按照一定的顺序选择每个物品,并尽可能的装入背包,知道背包装满。至少有三种看似合适的贪心策略。
选择价值最大的物品,因为这可以尽可能快的增加背包的总价值,但是,虽然每一步选择获得了背包价值的极大增长,但背包容量却可能消耗的太快,使得装入背包的物品个数减少,从而不能保证目标函数达到最大。
选择重量最轻的物品,因为这可以装入尽可能多的物品,从而增加背包的总价值。但是,虽然每一步选择使背包的容量消耗的慢了,但背包的价值却没能保证迅速的增长,从而不能保证目标函数达到最大。
以上两种贪心策略或者只考虑背包价值的增长,或者只考虑背包容量的消耗,而为了求得背包问题的最优解,需要在背包价值增长和背包容量消耗二者之间寻找平衡。正确的贪心策略是选择单位重量价值最大的物品。
例如:有三个物品,其重量分别为{20,30,10},价值分别为{60,120,50},背包的容量为50,应用三种贪心策略装入背包的物品和获得的价值如下图所示:
三、【算法:】
设背包容量为C,共有n个物品,物品重量存放在数组W[n]中,价值存放在数组V[n]中,问题的解存放在数组X[n]中,贪心法求解背包问题的算法如下:
算法:贪心法求解背包问题
输入:背包的容量C,物品重量W[n],物品价值V[n]
输出:数组X[n]
改变数组W和V的排列顺序,使其按单位重量价值V[i]/W[i]降序排列;
将数组X[n]初始化为0;
i=0;
循环直到(W[i]>C)
4.1 将第i个物品放入背包:X[i]=1;
4.2 C=C-W[i];
4.3 i++;
X[i]=C/W[i]。
贪心算法的设计思想
贪心法的应用
- 哈夫曼编码
- 0-1背包问题
- 磁盘文件的存储
- 生产调度问题
- 信息查询