Data Stuctures And Algorthms a.docx
- 文档编号:6059378
- 上传时间:2023-01-03
- 格式:DOCX
- 页数:21
- 大小:31.59KB
Data Stuctures And Algorthms a.docx
《Data Stuctures And Algorthms a.docx》由会员分享,可在线阅读,更多相关《Data Stuctures And Algorthms a.docx(21页珍藏版)》请在冰豆网上搜索。
DataStucturesAndAlgorthmsa
数据结构
知识:
1.数据结构中对象的定义,存储的表示及操作的实现.
2.线性:
线性表、栈、队列、数组、字符串(广义表不考)
树:
二叉树
集合:
查找,排序
图(不考)
能力:
分析,解决问题的能力
过程:
●确定问题的数据。
●确定数据间的关系。
●确定存储结构(顺序-数组、链表-指针)
●确定算法
●编程
●算法评价(时间和空间复杂度,主要考时间复杂度)
一、数组
1、存放于一个连续的空间
2、一维~多维数组的地址计算方式
已知data[0][0]的内存地址,且已知一个元素所占内存空间S求data[i][j]在内存中的地址。
公式:
(add+(i*12+j)*S)(假设此数组为data[10][12])
注意:
起始地址不是data[0][0]时候的情况。
起始地址为data[-3][8]和情况;
3、顺序表的定义
存储表示及相关操作
4、顺序表操作中时间复杂度估计
5、字符串的定义(字符串就是线性表),存储表示
模式匹配算法(简单和KMP(不考))
6、特殊矩阵:
存储方法(压缩存储(按行,按列))
三对角:
存储于一维数组
三对角问题:
已知Aij能求出在一维数组中的下标k;已知下标k求Aij。
7、稀疏矩阵:
定义,存储方式:
三元组表、十字链表(属于图部分,不考)
算法
●数组中元素的原地逆置;对换
●在顺序表中搜索值为X的元素;
●在有序表中搜索值为X的元素;(折半查找)
●在顺序表中的第i个位置插入元素X;
●在顺序表中的第i个位置删除元素X;
●两个有序表的合并;算法?
线性表数据结构定义:
Typedefstruct{
intdata[max_size];
intlen;
}linear_list;
●模式匹配
●字符串相加
●求子串
●(i,j)<=>K注意:
不同矩阵所用的公式不同;
●稀疏矩阵的转置(两种方式,后种为妙)
●和数组有关的算法
例程:
求两个长整数之和。
a=130********
b=87081299
数组:
a[]:
13056952168
b[]:
87081299
由于以上的结构不够直观(一般越是直观越容易解决)将其改为:
a[]:
11 86125965031a[0]=11(位数)
b[]:
8 99218078000b[0]=8
c进位 01100111100
c[]:
11 76433044231c[0]的值(C位数)由c[max_s+1]决定!
注意:
在求C前应该将C(max_s+1)位赋0.否则为随机数;较小的整数高位赋0.
算法:
已知a,b两个长整数,结果:
c=a+b;
总共相加次数:
max_s=max(a[],b[])
程序:
for(i=1;i<=max_s;i++){
k=a[i]+b[i]+c[i];
c[i]=k%10;
c[i+1]=k/10;
}
求c位数:
if(c[max_s+1]==0)
c[0]=max_s;
else
c[0]=max_s+1;
以下代码是我编的(毕竟是初学者.不太简洁大家不要见怪!
):
/*两长整数相加*/
#include
#include
#definePRINprintf("\n");
intflag=0;/*a[0]>b[0]?
1:
0*/
/*max(a[],b[]){}*/
change(charda[],chardb[],inta[],intb[],intc[]){
inti;
if(a[0]>b[0]){
for(i=1;i<=a[0];a[i]=da[a[0]-i]-'0',i++);/*a[0]-'0'sogood!
*/
for(i=1;i<=b[0];b[i]=db[b[0]-i]-'0',i++);
for(i=b[0]+1;i<=a[0];b[i]=0,i++);
for(i=1;i<=a[0]+1;c[i]=0,i++);
flag=1;
}
else{
for(i=1;i<=b[0];b[i]=db[b[0]-i]-'0',i++);
for(i=1;i<=a[0];a[i]=da[a[0]-i]-'0',i++);
for(i=a[0]+1;i<=b[0];a[i]=0,i++);
for(i=1;i<=b[0]+1;c[i]=0,i++);
}
}
add(inta[],intb[],intc[]){
inti,sum;
if(flag==1){
for(i=1;i<=a[0];i++){
sum=a[i]+b[i]+c[i];
c[i+1]=sum/10;
c[i]=sum%10;
}
if(c[a[0]+1]==0)
c[0]=a[0];
else
c[0]=a[0]+1;
}
else{
for(i=1;i<=b[0];i++){
sum=a[i]+b[i]+c[i];
c[i+1]=sum/10;
c[i]=sum%10;
}
if(c[b[0]+1]==0)
c[0]=b[0];
else
c[0]=b[0]+1;
}
}
voidprint(intm[]){
inti;
for(i=m[0];i>=1;i--)
printf("%d,",m[i]);PRIN
}
main(){
ints;
inta[20],b[20],c[20];
charda[]={"123456789"};
chardb[]={"12344443"};
a[0]=strlen(da);
b[0]=strlen(db);
printf("a[0]=%d\t",a[0]);
printf("b[0]=%d",b[0]);PRIN
change(da,db,a,b,c);
printf("flag=%d\n",flag);PRIN
printf("-----------------\n");
if(flag==1){
print(a);PRIN
s=abs(a[0]-b[0]);
printf("+");
for(s=s*2-1;s>0;s--)
printf("");
print(b);PRIN
}
else{
s=abs(a[0]-b[0]);
printf("+");
for(s=s*2-1;s>0;s--)
printf("");
print(a);PRIN
print(b);PRIN
}
add(a,b,c);
printf("-----------------\n");
print(c);
}
时间复杂度计算:
●确定基本操作
●计算基本操作次数
●选择T(n)
●lim(F(n)/T(n))=c
●0(T(n))为时间复杂度
上例子的时间复杂度为O(max_s);
二:
链表
1、知识点
●逻辑次序与物理次序不一致存储方法;
●单链表的定义:
术语(头结点、头指针等)
●注意带头结点的单链表与不带头结点的单链表区别。
(程序员考试一般不考带头结点,因为稍难理解)
●插入、删除、遍历(p==NULL表明操作完成)等操作
●循环链表:
定义,存储表示,操作;
●双向链表:
定义,存储方法,操作;
单链表和循环链表区别在最后一个指针域值不同。
2、操作
●单链表:
插入X,删除X,查找X,计算结点个数
●单链表的逆置(中程曾考)
head->NULL/p->a1/p->a2/p->a3/p……an/NULL注:
p代表指针;NULL/p代表头结点
=》head->NULL/p->an/p->an-1/p->an-2/p……a1/NULL
●循环链表的操作:
插入X,删除X,查找X,计算结点个数;
用p=head->next来判断一次计算结点个数完成;
程序段如下:
k=0;
do{
k++;
p=p->next;
}while(p!
=head->next);
●双向链表
●多项式相加
●有序链表合并
例程:
已知两个字符串S,T,求S和T的最长公子串;
1、逻辑结构:
字符串
2、存储结构:
数组
3、算法:
精化(精细化工)**老顽童注:
此处“精细化工”说明好像不对!
s="abaabcacb"
t="abdcabcaabcda"
当循环到s.len-1时,有两种情况:
s="abaabcacb"、s="abaabcacb"
s.len-2时,有三种情况:
s="abaabcacb"、s="abaabcacb"、s="abaabcacb"
.
.
.
1s.len种情况
程序思路:
tag=0//没有找到
for(l=s.len;l>0&&!
tag;l--){
判断长度为l的s中的子串是否为t的子串;
若是:
tag=1;
}
长度为l的s的子串在s中有(s.len-l+1)个。
子串0:
0~l-1
1:
1~l
2:
2~l+1
3:
3~l+2
……
……
s.len-l:
s.len-l~s.len-1
由上面可得:
第j个子串为j~l+j-1。
判断长度为l的s中的子串是否为t的子串:
for(j=0;j tag;j++){ 判断s中长度为l的第j个子串是否为t的子串; 如果是: tag=1; } 模式结构: tag=0; for(l=s.len;l>0&&tag==0;l--){ for(j=0;j tag;j++){ ? ? 用模式匹配方法确定s[j]~s[l+j-1]这个字符串是否为t的子串;//好好想想 若是,tag=1; } } 栈和队列 1、知识点: ●栈的定义: 操作受限的线性表 ●特点: 后进先出 ●栈的存储结构: 顺序,链接 /push(s,d) ●栈的基本操作: \pop(s) 栈定义: struct{ datatypedata[max_num]; inttop; }; ●队列定义 特点: 先进先出 /入队列in_queue(Q,x) ●队列的操作: \出队列del_queue(Q) ●队列存储结构: 链队列: Typedefstructnode{ Datatypedata; Structnode*next; }NODE; Typedefstruct{ NODE*front; NODE*rear; }Queue; 顺序队列: struct{ datatypedata[max_num]; intfront,rear; }; 问题: 队列⇔线性表 假溢出<=循環队列 队列满,队列空条件一样<=浪费一个存储空间 递归 定义: 问题规模为N的解依赖于小规模问题的解。 问题的求解通过小规模问题的解得到。 包括二个步骤: 1)递推6! =>5! =>4! =>3! =>2! =>1! =>0! 2)回归720<=120<=24<=6<=2<=1<=0 递归工作栈实现递归的机制。 2、有关算法: 1)顺序,链表结构下的出栈,入栈 2)循環,队列的入队列,出队列。 3)链队列的入队列,出队列。 4)表达式计算: 后缀表达式35+6/4368/+*- 中缀表达式(3+5)/6-4*(3+6/8) 由于中缀比较难处理,计算机内一般先将中缀转换为后缀。 运算: 碰到操作数,不运算,碰到操符,运算其前两个操作数。 中缀=>后缀 5)迷宫问题 6)线性链表的递归算法一个链表=一个结点+一个链表 intfuction(NODE*p){ if(p==NULL)return0; elsereturn(function(p->next)); } 树与二叉树 一、知识点: 1.树的定义: data_struct(D,R); 其中: D中有一个根,把D和出度去掉,可以分成M个部分. D1,D2,D3,D4,D5…DM R1,R2,R3,R4,R5…RM 而子树Ri形成树. 1)递归定义高度 2)结点个数=1 O --0 O O --1 O O O O --2 此树的高度为2 2.二叉树定义: 结点个数>=0. 3.术语: 左右孩子,双亲,子树,度,高度等概念. 4.二叉树的性质 ●层次为I的二叉树I层结点2I个 ●高度为H的二叉树结点2H+1-1个 ●H(点)=E(边)+1 ●个数为N的完全二叉树高度为|_LOG2n_| ●完全二叉树结点编号: 从上到下,从左到右. i结点的双亲: |_i/2_| |_i-1/2_| 1 i结点的左孩子: 2i 2i+1 2 3 i结点的右孩子: 2i+1 2i+2 4 5 6 7 (根) 1为起点 0为起点 二叉树的存储结构: 1)扩展成为完全二叉树,以一维数组存储。 A B C D E F G H I 数组下标 0 1 2 3 4 5 6 7 8 9 10 11 12 元素 A B C D E F G H I 2)双亲表示法 数组下标 0 1 2 3 4 5 6 7 8 元素 A B C D E F G H I 双亲 -1 0 0 1 2 2 3 3 4 3)双亲孩子表示法 数组下标 0 1 2 3 4 5 … 元素 A B C D E F … 双亲 -1 0 0 1 2 2 … 左子 1 3 4 … 右子 2 -1 5 … 结构: typedefstruct{ datatypedata; intparent; intlchild; intrchild; }NODE; NODEtree[N];//生成N个结点的树 4)二叉链表 5)三叉链表 6)哈夫曼树 5.二叉树的遍历 先根\ 中根栈中根遍历(左子树)根(右子树),再用相同的方法处理左子树,右子树. 后根/ 先,中序已知求树: 先序找根,中序找确定左右子树. 层次遍历(队列实现) 6.线索二叉树(穿线树) 中序线索二树树目的: 利用空指针直接得到中序遍历的结果. 手段(方法): 左指针为空,指向前趋,右指针为空,指向后继. 结点结构: ltag Lch Data rch rtag Ltag=0,lch指向左孩子,ltag=1,指向前趋结点 Rtag=0,rch指向右孩子;rtag=1,指向后继结点 中序遍历: 1)找最左结点(其左指针为空) 2)当该结点的rtag=1,该结点的rch指向的就为后继 3)当rtag=0,后继元素为右子树中最左边那个 N个结点的二树有空指针N+1个 周六我去了周SIR的办公室,他很热情,我问的是中序线索化二叉树的问题(递归),关于这个问题我会在以后的笔记中作重点补充。 我在这学校从来没有碰到过像他这样热情的老师,真的,大一的时候我们学校就开了C,当时我就连#include 《数据结构》的课程设计也是哈科大的littlebob兄帮我做的,很遗憾,他高程就差几分,希望他早日成功,我们都要向他学习)等于说我的C知识九成都是在大二下学期的时候学的。 而且全是自学的。 拿这个周末来说吧。 我三天时间就看完了一本C语言大全。 当然,并不是从头到尾,只是根据自己的实际情况,重点是指针和数据结构那块。 C最要的便是指针。 程序员考试下午试题最重要的便是递归问题(1~2道,没有掌握就没希望了哦)。 我说这些并不是为了表明自己多么用功,只是希望每位"学者"都有所侧重。 查找 一、知识点 /静态查找->数组 1、什么是查找 \动态查找->链树 ●顺序查找,时间复杂度O(n) ●折半查找: 条件: 有序;时间复杂度O(nlog2n)(时间复杂度实际上是查找树的高度) ●索引查找: 条件: 第I+1块的所有元素都大于第I块的所有元素。 算法: 根据index来确定X所在的块(i)时间复杂度: m/2 在第I块里顺序查找X 时间复杂度: n/2 总的时间复杂度: (m+n)/2 ●二叉排序树 1)定义: 左子树键值大于根节点键值;右子树键值小于根的键值,其左右子树均为二叉排序树。 2)特点: 中序遍历有序->(删除节点用到此性质) 3)二叉排序树的查找: 如果根大于要查找的树,则前左子树前进,如果根小于要查找的树,则向右子树前进。 4)结点的插入->二叉排序树的构造方法 5)结点删除(难点) 1、右子树放在左子树的最右边 2、左子树放在右子树的最左边 ●avl树(二叉平衡树): 左右子树高度只能差1层,即|h|<=1其子树也一样。 ●B树: n阶B树满足以下条件 1)每个结点(除根外)包含有N~2N个关链字。 2)所有叶子节点都在同一层。 3)B树的所有子树也是一棵B树。 特点: 降低层次数,减少比较次数。 排序 一、知识点 1、排序的定义 /内排序: 只在内存中进行 2、排序的分类 \外排序: 与内外存进行排序 内排序: /直接插入排序 1)插入排序 \shell排序 /冒泡排序 2)交换排序 \快速排序 /简单选择排序 3)选择排序堆 \锦标赛排序 4)归并排序(二路) 5)基数排序(多关链字排序) 3、时间复杂度(上午题目常考,不会求也得记住啊兄弟姐妹们! ) ******15***15*** /稳定 ********1515****(前后不变) 排序 \不稳定 ********1515****(前后改变) 经整理得: 选择、希尔、堆、快速排序是不稳定的;直接插入、冒泡、合并排序是稳定的。 ●锦标赛排序方法: 13 16 11 18 21 3 17 6 \ / \ / \ / \ / 13 11 3 6 \ / \ / 11 3 \ / 3(胜出,将其拿出,并令其为正无穷&GoOn) ●归并排序方法: 13 16 11 18 21 3 17 6 \ / \ / \ / \ / 13,16 11,18 3,21 6,17 \ / \ / 11,13,16,18
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Data Stuctures And Algorthms