程序员数据结构笔记.docx

上传人:b****3 文档编号:4312594 上传时间:2022-11-29 格式:DOCX 页数:26 大小:36.03KB
下载 相关 举报
程序员数据结构笔记.docx_第1页
第1页 / 共26页
程序员数据结构笔记.docx_第2页
第2页 / 共26页
程序员数据结构笔记.docx_第3页
第3页 / 共26页
程序员数据结构笔记.docx_第4页
第4页 / 共26页
程序员数据结构笔记.docx_第5页
第5页 / 共26页
点击查看更多>>
下载资源
资源描述

程序员数据结构笔记.docx

《程序员数据结构笔记.docx》由会员分享,可在线阅读,更多相关《程序员数据结构笔记.docx(26页珍藏版)》请在冰豆网上搜索。

程序员数据结构笔记.docx

程序员数据结构笔记

http:

//www.yuanma.org/data/2007/0614/article_2676.htm

数据结构

知识:

  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;

   }

  }

第二天 

  转眼又过了一周了,前面一周里面我编了一些程序:

链表,长整型数相加,三元组表转置以及一些简单的函数.其实有些算法想想是很简单,不过写起来还是需要一定耐心和C基础的,如果你自己觉得各算法都很懂了,不妨开机编编试试.或许会有一些新的发现与体会.

栈和队列

  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

                 \          /

                 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 经济市场

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1