分治算法(思想)在数据结构中的应用
2015-10-06 08:48
363 查看
分治算法:
简单的概括就是将暂时不能解决的大问题分成许多入门的子问题,
如果子问题还是不能解决的话则继续分成子问题,直到子问题小到
可以解决为止的规模,原问题即是子问题的合并。
PartOne:
用分治法打印数组a[L,......,R].
分析:
一个循环就可以了,但是分治算法来解决该怎么做呢?
如果待打印的序列长度为 1,则可以直接打印;
如果待打印的序列长度为 N,则可将其划分为两部分;
第一部分是 1, 后N - 1 是另一个划分,以此类推,直到数组长度是 1.
void print(int a[], int L, int R)
{
if(L > R)
return;
else if(L == R)
{
cout<<"a[L]"<<" ";
}
else
{
cout<<a[L]<<" ";
print(a, L + 1, R);
}
}
PartTwo:
假设存在一个函数divid(),可以将一个数组a[L,...,R]分成两部分,
元素a[L]为分界线,小于a[L]的元素在左边,大于啊a[L]的元素在右边
函数声明如下:
int divid(int a[], int L, int R);
试用分治法,对数组a[L,...R]中元素进行快速排序
分析:
如果长度小于1,则默认有序, 如果序列长度大于1则用divid()函数
将其划分为3部分,左边是小于a[L]的部分,中间是a[L], 右边是大于
a[L]的部分。a[L]已经有序,则只需要对其左右两部分进行分支处理。
void Qsort()
{
int mid;
if(L >= R)
return;
else
{
mid = divid(a, L, R);
Qsort(a, L, mid);
Qsort(a, mid + 1, R);
}
}
PartThree;
一颗二叉树存储在二叉链表中,用分治法打印所有的结点值,
根结点由 p 所指。
分析:
当树为空的时候,什么都不用做,问题直接解决。
当树中结点树大于等于 1 的时候,把整棵树划分为根, 左子树,
右子树三部分。根结点直接打印,对左子树继续分治处理,
对右子树继续分治处理,最终打印整棵二叉树。
void printTree(BTNode *p)
{
if(p == NULL)
return;
else
{
cout<<p->data<<" ";
printTree(p->lchild);
printTree(p->rchild);
}
}
PartFour:
一个连通图G用邻接表存储,用分治法打印图中的所有定顶点值,假设从顶点 v 开始打印,
则可将整个图分成 n 部分,接着和上一个例子很像可以把图分成,第一条边所达到的子图,
第二条边所达到的子图........第N条边达到的子图。V可以直接打印,然后对各个子图分别分治处理。
为了防止出现回路现象,则可以设置一个数组visited[]标记已经走过的路。
(深度优先搜索的分治解释)
void printGraph(AGraph *G, int v)
{
ArcNode *p;
visited[v] = 1;
cout<<v<<" ";
p = G->adjlist[v].firstarc;
while(p != NULL)
{
if(visited[p->adjvex] == 0)
{
printGraph(G, p->adjvex);
}
p = p->nextarc;
}
}
PartFive:
已知二叉树的先序遍历序列和中序遍历序列,分别存储在a[L1,....,R1],
b[L2,...R2];两个数组中,用分治算法由这两个序列建立一颗二叉树,
存储在二叉链表存储的结构中。
分析:
如果为空序列,则什么也不用做。如果是长度大于 1,则a[L1]位二叉树
的根结点,在b[]中找到a[L],假设下标为k,则b[L2,.....k - 1]是其左子树上
的所有结点,b[k + 1, .... R2]是其右子树上的所有结点反应在 a[ ]中即
a[L1 + 1,... L1 + k - L2]与b[L2, .... , k-1]继续进行分治处理。最终可将树创建完毕。
BTNode* Create(int a[], int b[], int L1, int R1, int L2, int R2)
{
int k;
if(L1 > R1)
return NULL;
else
{
s = (BTNode*)malloc(sizeof(BTNode));
s->data = a[L1];
for(k = L2; k < R2; ++k)
{
if(a[L1] == b[K])
{
break;
}
}
s->lchild = Create(a, b, L1 + 1, L1 + k - L2, L2, k - 1);
s->lchild = Create(a, b, L1 + k - L2 + 1, R1, k + 1, R2);
}
}
简单的概括就是将暂时不能解决的大问题分成许多入门的子问题,
如果子问题还是不能解决的话则继续分成子问题,直到子问题小到
可以解决为止的规模,原问题即是子问题的合并。
PartOne:
用分治法打印数组a[L,......,R].
分析:
一个循环就可以了,但是分治算法来解决该怎么做呢?
如果待打印的序列长度为 1,则可以直接打印;
如果待打印的序列长度为 N,则可将其划分为两部分;
第一部分是 1, 后N - 1 是另一个划分,以此类推,直到数组长度是 1.
void print(int a[], int L, int R)
{
if(L > R)
return;
else if(L == R)
{
cout<<"a[L]"<<" ";
}
else
{
cout<<a[L]<<" ";
print(a, L + 1, R);
}
}
PartTwo:
假设存在一个函数divid(),可以将一个数组a[L,...,R]分成两部分,
元素a[L]为分界线,小于a[L]的元素在左边,大于啊a[L]的元素在右边
函数声明如下:
int divid(int a[], int L, int R);
试用分治法,对数组a[L,...R]中元素进行快速排序
分析:
如果长度小于1,则默认有序, 如果序列长度大于1则用divid()函数
将其划分为3部分,左边是小于a[L]的部分,中间是a[L], 右边是大于
a[L]的部分。a[L]已经有序,则只需要对其左右两部分进行分支处理。
void Qsort()
{
int mid;
if(L >= R)
return;
else
{
mid = divid(a, L, R);
Qsort(a, L, mid);
Qsort(a, mid + 1, R);
}
}
PartThree;
一颗二叉树存储在二叉链表中,用分治法打印所有的结点值,
根结点由 p 所指。
分析:
当树为空的时候,什么都不用做,问题直接解决。
当树中结点树大于等于 1 的时候,把整棵树划分为根, 左子树,
右子树三部分。根结点直接打印,对左子树继续分治处理,
对右子树继续分治处理,最终打印整棵二叉树。
void printTree(BTNode *p)
{
if(p == NULL)
return;
else
{
cout<<p->data<<" ";
printTree(p->lchild);
printTree(p->rchild);
}
}
PartFour:
一个连通图G用邻接表存储,用分治法打印图中的所有定顶点值,假设从顶点 v 开始打印,
则可将整个图分成 n 部分,接着和上一个例子很像可以把图分成,第一条边所达到的子图,
第二条边所达到的子图........第N条边达到的子图。V可以直接打印,然后对各个子图分别分治处理。
为了防止出现回路现象,则可以设置一个数组visited[]标记已经走过的路。
(深度优先搜索的分治解释)
void printGraph(AGraph *G, int v)
{
ArcNode *p;
visited[v] = 1;
cout<<v<<" ";
p = G->adjlist[v].firstarc;
while(p != NULL)
{
if(visited[p->adjvex] == 0)
{
printGraph(G, p->adjvex);
}
p = p->nextarc;
}
}
PartFive:
已知二叉树的先序遍历序列和中序遍历序列,分别存储在a[L1,....,R1],
b[L2,...R2];两个数组中,用分治算法由这两个序列建立一颗二叉树,
存储在二叉链表存储的结构中。
分析:
如果为空序列,则什么也不用做。如果是长度大于 1,则a[L1]位二叉树
的根结点,在b[]中找到a[L],假设下标为k,则b[L2,.....k - 1]是其左子树上
的所有结点,b[k + 1, .... R2]是其右子树上的所有结点反应在 a[ ]中即
a[L1 + 1,... L1 + k - L2]与b[L2, .... , k-1]继续进行分治处理。最终可将树创建完毕。
BTNode* Create(int a[], int b[], int L1, int R1, int L2, int R2)
{
int k;
if(L1 > R1)
return NULL;
else
{
s = (BTNode*)malloc(sizeof(BTNode));
s->data = a[L1];
for(k = L2; k < R2; ++k)
{
if(a[L1] == b[K])
{
break;
}
}
s->lchild = Create(a, b, L1 + 1, L1 + k - L2, L2, k - 1);
s->lchild = Create(a, b, L1 + k - L2 + 1, R1, k + 1, R2);
}
}
相关文章推荐
- 数据结构实践项目——队列
- 数据结构实践——队列数组
- 数据结构: Java中LinkedList的简单实现
- 数据结构: Java中ArrayList的简单实现
- dlutoj 单调队列
- 数据结构实践——负数把正数赶出队列
- 数据结构实践——停车场模拟(栈和队列综合)
- 大话数据结构(2)--数据-横看成岭侧成峰
- iOS编程------XML、JSON数据结构解析
- [面试时]MySQL索引背后的数据结构及算法原理
- 数据结构实践——排队看病模拟(队列)
- POJ 2823 单调队列
- 【数据结构】线性结构:存储&运算&时间复杂度
- 数据结构之线性表
- Linux的常用数据结构之链表
- 数据结构【线性表(二)链表】项目之猴子选大王
- 第4周SHH数据结构—【项目3-单链表应用(1)】
- 数据结构【线性表(二)链表】项目之循环双链表应用
- 数据结构实践——多项式求和
- 第六周项目2—数据结构之自建算法库—链栈