博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
读《程序是怎样跑起来的》第4章
阅读量:5217 次
发布时间:2019-06-14

本文共 12180 字,大约阅读时间需要 40 分钟。

   指针指的是用于存储内存地址的变量;物理内存以字节为单位进行数据存储的;栈是一种后入先出(LIFO=Last In First Out)式的数据结构;二叉查找树指的是从节点分成两个叉的树状数据结构。内存IC中有电源、地址信号、数据信号、控制信号等用于输入输出的大量引脚(IC的引脚),通过为其指定地址(address),来进行数据的读写。

1 #include "stdio.h"      2 #include "stdlib.h"     3 #include "io.h"    4 #include "math.h"    5 #include "time.h"  6   7 #define OK 1  8 #define ERROR 0  9 #define TRUE 1 10 #define FALSE 0 11 #define MAXSIZE 20 /* 存储空间初始分配量 */ 12  13 typedef int Status;  14 typedef int SElemType; /* SElemType类型根据实际情况而定,这里假设为int */ 15  16 /* 顺序栈结构 */ 17 typedef struct 18 { 19         SElemType data[MAXSIZE]; 20         int top; /* 用于栈顶指针 */ 21 }SqStack; 22  23 Status visit(SElemType c) 24 { 25         printf("%d ",c); 26         return OK; 27 } 28  29 /*  构造一个空栈S */ 30 Status InitStack(SqStack *S) 31 {  32         /* S.data=(SElemType *)malloc(MAXSIZE*sizeof(SElemType)); */ 33         S->top=-1; 34         return OK; 35 } 36  37 /* 把S置为空栈 */ 38 Status ClearStack(SqStack *S) 39 {  40         S->top=-1; 41         return OK; 42 } 43  44 /* 若栈S为空栈,则返回TRUE,否则返回FALSE */ 45 Status StackEmpty(SqStack S) 46 {  47         if (S.top==-1) 48                 return TRUE; 49         else 50                 return FALSE; 51 } 52  53 /* 返回S的元素个数,即栈的长度 */ 54 int StackLength(SqStack S) 55 {  56         return S.top+1; 57 } 58  59 /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */ 60 Status GetTop(SqStack S,SElemType *e) 61 { 62         if (S.top==-1) 63                 return ERROR; 64         else 65                 *e=S.data[S.top]; 66         return OK; 67 } 68  69 /* 插入元素e为新的栈顶元素 */ 70 Status Push(SqStack *S,SElemType e) 71 { 72         if(S->top == MAXSIZE -1) /* 栈满 */ 73         { 74                 return ERROR; 75         } 76         S->top++;                /* 栈顶指针增加一 */ 77         S->data[S->top]=e;  /* 将新插入元素赋值给栈顶空间 */ 78         return OK; 79 } 80  81 /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */ 82 Status Pop(SqStack *S,SElemType *e) 83 {  84         if(S->top==-1) 85                 return ERROR; 86         *e=S->data[S->top];    /* 将要删除的栈顶元素赋值给e */ 87         S->top--;                /* 栈顶指针减一 */ 88         return OK; 89 } 90  91 /* 从栈底到栈顶依次对栈中每个元素显示 */ 92 Status StackTraverse(SqStack S) 93 { 94         int i; 95         i=0; 96         while(i<=S.top) 97         { 98                 visit(S.data[i++]); 99         }100         printf("\n");101         return OK;102 }103 104 int main()105 {106         int j;107         SqStack s;108         int e;109         if(InitStack(&s)==OK)110                 for(j=1;j<=10;j++)111                         Push(&s,j);112         printf("栈中元素依次为:");113         StackTraverse(s);114         Pop(&s,&e);115         printf("弹出的栈顶元素 e=%d\n",e);116         printf("栈空否:%d(1:空 0:否)\n",StackEmpty(s));117         GetTop(s,&e);118         printf("栈顶元素 e=%d 栈的长度为%d\n",e,StackLength(s));119         ClearStack(&s);120         printf("清空栈后,栈空否:%d(1:空 0:否)\n",StackEmpty(s));121         122         return 0;123 }

 

  随机存取存储器,又称做随机存储器是与CPU直接交换数据的内部存储器,主存主要是指RAM。RAM随时时读写,而且速度很快,但当电源关闭时不能保留数据,通常作为操作系统或其它正在运行中的程序的临时数据存储媒介。主存是计算机内部最主要的内存用来加载各式各样的程序与数据,一共cpu直接使用RAM可以分为动态随机存储器DRAM和静态随机存储器SRAM两大类。DRAM需要定时刷新单,由于具有较低的单位价格,扩展性也不错,所以也被大量的采用作为系统的主存。而SRAM不需要刷新,因此具有快速访问的优点,生产成本较昂贵,一个典型的应用就是高速缓存。

  使用高速缓存的原因:由于CPU的运行速度一般比内存的读取速度快,而且内存周期(访问内存所需要的时间)为数个时钟周期,因此若要访问内存就必须等待数个CPU时钟周期,从而造成浪费。

高速缓存的基本原理:是内存中”程序执行与数据访问的局域性行为”,即一定程序执行时间和空间内被访问的代码集中于一部分。为了充分发挥高速缓存的作用,不仅依靠“暂存刚刚访问过的数据”还要使用硬件实现指令的预测和数据预取技术,尽可能把将要使用的数据预先从内存中取到高速缓存中。

  只读存储器ROM,是一种半导体存储器,其特性是一旦存储数据就无法再将之改变,或删除其数据,只能读不能写入和修改。其内容不会因为电源关闭而消失,通常用于存储,不需要经常变更的程序和数据,如BIOS和启动程序。

  固件是一种嵌入在硬件设备的软件(程序和数据),固件位于软件和硬件之间,是软件和硬件的合成品,通常它位于特殊的应用集成电路(ASIC)或可编程逻辑器件PLD之中的闪存或EEPROM或PROM里,有的可以让用户更新。固件广泛应用于在各种电子产品中,从计算器到计算机的键盘、硬盘、内存卡、甚至科学计算和工业机器人。日常生活中的移动电话,数码相机,电视遥控器等均包含固件,以执行设备的基本操作和高级功能。

  互补式金属氧化物半导体(CMOS)是一种集成电路,半导体可在硅晶圆上制作出PMOS(正极)和NMOS(负极)元件,由于PMOS与NMOS在特性上为互补性,因此称为CMOS。此半导体可用来制作微处理器(Microprocessor)、微控制器(Microcontroller)、静态随机存取内存(SRAM)以及其他数位逻辑电路。CMOS具有只有在晶体管需要切换启闭时才需耗能的优点,非常省电且发热少,因此特别适合电池供电的设备。个人计算机中有一个电池供电的CMOS,存储系统日期、时间、启动参数等。即CMOS:存储计算机的启动信息;存储计算机的配置信息(如磁盘驱动器类型、键盘、显示器等)。

1 #include "stdio.h"      2 #include "stdlib.h"     3 #include "io.h"    4 #include "math.h"    5 #include "time.h"  6   7 #define OK 1  8 #define ERROR 0  9 #define TRUE 1 10 #define FALSE 0 11 #define MAXSIZE 20 /* 存储空间初始分配量 */ 12  13 typedef int Status;  14 typedef int QElemType; /* QElemType类型根据实际情况而定,这里假设为int */ 15  16 /* 循环队列的顺序存储结构 */ 17 typedef struct 18 { 19     QElemType data[MAXSIZE]; 20     int front;        /* 头指针 */ 21     int rear;        /* 尾指针,若队列不空,指向队列尾元素的下一个位置 */ 22 }SqQueue; 23  24 Status visit(QElemType c) 25 { 26     printf("%d ",c); 27     return OK; 28 } 29  30 /* 初始化一个空队列Q */ 31 Status InitQueue(SqQueue *Q) 32 { 33     Q->front=0; 34     Q->rear=0; 35     return  OK; 36 } 37  38 /* 将Q清为空队列 */ 39 Status ClearQueue(SqQueue *Q) 40 { 41     Q->front=Q->rear=0; 42     return OK; 43 } 44  45 /* 若队列Q为空队列,则返回TRUE,否则返回FALSE */ 46 Status QueueEmpty(SqQueue Q) 47 {  48     if(Q.front==Q.rear) /* 队列空的标志 */ 49         return TRUE; 50     else 51         return FALSE; 52 } 53  54 /* 返回Q的元素个数,也就是队列的当前长度 */ 55 int QueueLength(SqQueue Q) 56 { 57     return  (Q.rear-Q.front+MAXSIZE)%MAXSIZE; 58 } 59  60 /* 若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR */ 61 Status GetHead(SqQueue Q,QElemType *e) 62 { 63     if(Q.front==Q.rear) /* 队列空 */ 64         return ERROR; 65     *e=Q.data[Q.front]; 66     return OK; 67 } 68  69 /* 若队列未满,则插入元素e为Q新的队尾元素 */ 70 Status EnQueue(SqQueue *Q,QElemType e) 71 { 72     if ((Q->rear+1)%MAXSIZE == Q->front)    /* 队列满的判断 */ 73         return ERROR; 74     Q->data[Q->rear]=e;            /* 将元素e赋值给队尾 */ 75     Q->rear=(Q->rear+1)%MAXSIZE;/* rear指针向后移一位置, */ 76                                 /* 若到最后则转到数组头部 */ 77     return  OK; 78 } 79  80 /* 若队列不空,则删除Q中队头元素,用e返回其值 */ 81 Status DeQueue(SqQueue *Q,QElemType *e) 82 { 83     if (Q->front == Q->rear)            /* 队列空的判断 */ 84         return ERROR; 85     *e=Q->data[Q->front];                /* 将队头元素赋值给e */ 86     Q->front=(Q->front+1)%MAXSIZE;    /* front指针向后移一位置, */ 87                                     /* 若到最后则转到数组头部 */ 88     return  OK; 89 } 90  91 /* 从队头到队尾依次对队列Q中每个元素输出 */ 92 Status QueueTraverse(SqQueue Q) 93 {  94     int i; 95     i=Q.front; 96     while((i+Q.front)!=Q.rear) 97     { 98         visit(Q.data[i]); 99         i=(i+1)%MAXSIZE;100     }101     printf("\n");102     return OK;103 }104 105 int main()106 {107     Status j;108     int i=0,l;109     QElemType d;110     SqQueue Q;111     InitQueue(&Q);112     printf("初始化队列后,队列空否?%u(1:空 0:否)\n",QueueEmpty(Q));113 114     printf("请输入整型队列元素(不超过%d个),-1为提前结束符: ",MAXSIZE-1);115     do116     {117         /* scanf("%d",&d); */118         d=i+100;119         if(d==-1)120             break;121         i++;122         EnQueue(&Q,d);123     }while(i
0)142 printf("现在由队头删除%d个元素:\n",l-2);143 while(QueueLength(Q)>2)144 {145 DeQueue(&Q,&d);146 printf("删除的元素值为%d\n",d);147 }148 149 j=GetHead(Q,&d);150 if(j)151 printf("现在队头元素为: %d\n",d);152 ClearQueue(&Q);153 printf("清空队列后, 队列空否?%u(1:空 0:否)\n",QueueEmpty(Q));154 return 0;155 }

  数组是内存使用方法的基础,因为数组和内存的物理构造是一样的。特别是以字节类型的数组,它和内存的物理构造完全一致。不过如果只能逐个字节来读写,程序变得比较麻烦,因而可以指定任意数据类型来定义数组。数组还有一些变形方法,栈、队列、链表和二叉查找树。栈和队列都可以不通过指定地址和索引来对数组的元素进行读写。栈和队列的区别在于数据出入的顺序是不同的。在对内存数据进行读写时,栈用的是LIFO(Last Input Fisrt Out)后入先出方式,而队列用的则是FIFO(First Input First Out)先入先出方式。如果我们在内存中预留出栈和队列所需要的空间,并确定好写入和读出的顺序,就不用再指定地址和索引了。在数组的各个元素中,除了数据值之外,通过为其附带上下一个元素的索引,即可实现链表,从而可使得元素的追加和删除更容易。二叉查找树是在链表的基础上往数组中追加元素时,考虑到数据的大小关系,将其分成左右两个方向的表现形式,从而使数据搜索更有效。

1 #include "string.h"  2 #include "stdio.h"      3 #include "stdlib.h"     4 #include "io.h"    5 #include "math.h"    6 #include "time.h"  7   8 #define OK 1  9 #define ERROR 0 10 #define TRUE 1 11 #define FALSE 0 12  13 #define MAXSIZE 100 /* 存储空间初始分配量 */ 14  15 typedef int Status;        /* Status是函数的类型,其值是函数结果状态代码,如OK等 */ 16  17 /* 用于构造二叉树********************************** */ 18 int index=1; 19 typedef char String[24]; /*  0号单元存放串的长度 */ 20 String str; 21  22 Status StrAssign(String T,char *chars) 23 {  24     int i; 25     if(strlen(chars)>MAXSIZE) 26         return ERROR; 27     else 28     { 29         T[0]=strlen(chars); 30         for(i=1;i<=T[0];i++) 31             T[i]=*(chars+i-1); 32         return OK; 33     } 34 } 35 /* ************************************************ */ 36  37 typedef char TElemType; 38 TElemType Nil=' '; /* 字符型以空格符为空 */ 39  40 Status visit(TElemType e) 41 { 42     printf("%c ",e); 43     return OK; 44 } 45  46 typedef struct BiTNode  /* 结点结构 */ 47 { 48    TElemType data;        /* 结点数据 */ 49    struct BiTNode *lchild,*rchild; /* 左右孩子指针 */ 50 }BiTNode,*BiTree; 51  52  53 /* 构造空二叉树T */ 54 Status InitBiTree(BiTree *T) 55 {  56     *T=NULL; 57     return OK; 58 } 59  60 /* 初始条件: 二叉树T存在。操作结果: 销毁二叉树T */ 61 void DestroyBiTree(BiTree *T) 62 {  63     if(*T)  64     { 65         if((*T)->lchild) /* 有左孩子 */ 66             DestroyBiTree(&(*T)->lchild); /* 销毁左孩子子树 */ 67         if((*T)->rchild) /* 有右孩子 */ 68             DestroyBiTree(&(*T)->rchild); /* 销毁右孩子子树 */ 69         free(*T); /* 释放根结点 */ 70         *T=NULL; /* 空指针赋0 */ 71     } 72 } 73  74 /* 按前序输入二叉树中结点的值(一个字符) */ 75 /* #表示空树,构造二叉链表表示二叉树T。 */ 76 void CreateBiTree(BiTree *T) 77 {  78     TElemType ch; 79      80     /* scanf("%c",&ch); */ 81     ch=str[index++]; 82  83     if(ch=='#')  84         *T=NULL; 85     else 86     { 87         *T=(BiTree)malloc(sizeof(BiTNode)); 88         if(!*T) 89             exit(OVERFLOW); 90         (*T)->data=ch; /* 生成根结点 */ 91         CreateBiTree(&(*T)->lchild); /* 构造左子树 */ 92         CreateBiTree(&(*T)->rchild); /* 构造右子树 */ 93     } 94  } 95  96 /* 初始条件: 二叉树T存在 */ 97 /* 操作结果: 若T为空二叉树,则返回TRUE,否则FALSE */ 98 Status BiTreeEmpty(BiTree T) 99 { 100     if(T)101         return FALSE;102     else103         return TRUE;104 }105 106 #define ClearBiTree DestroyBiTree107 108 /* 初始条件: 二叉树T存在。操作结果: 返回T的深度 */109 int BiTreeDepth(BiTree T)110 {111     int i,j;112     if(!T)113         return 0;114     if(T->lchild)115         i=BiTreeDepth(T->lchild);116     else117         i=0;118     if(T->rchild)119         j=BiTreeDepth(T->rchild);120     else121         j=0;122     return i>j?i+1:j+1;123 }124 125 /* 初始条件: 二叉树T存在。操作结果: 返回T的根 */126 TElemType Root(BiTree T)127 { 128     if(BiTreeEmpty(T))129         return Nil;130     else131         return T->data;132 }133 134 /* 初始条件: 二叉树T存在,p指向T中某个结点 */135 /* 操作结果: 返回p所指结点的值 */136 TElemType Value(BiTree p)137 {138     return p->data;139 }140 141 /* 给p所指结点赋值为value */142 void Assign(BiTree p,TElemType value)143 {144     p->data=value;145 }146 147 /* 初始条件: 二叉树T存在 */148 /* 操作结果: 前序递归遍历T */149 void PreOrderTraverse(BiTree T)150 { 151     if(T==NULL)152         return;153     printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */154     PreOrderTraverse(T->lchild); /* 再先序遍历左子树 */155     PreOrderTraverse(T->rchild); /* 最后先序遍历右子树 */156 }157 158 /* 初始条件: 二叉树T存在 */159 /* 操作结果: 中序递归遍历T */160 void InOrderTraverse(BiTree T)161 { 162     if(T==NULL)163         return;164     InOrderTraverse(T->lchild); /* 中序遍历左子树 */165     printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */166     InOrderTraverse(T->rchild); /* 最后中序遍历右子树 */167 }168 169 /* 初始条件: 二叉树T存在 */170 /* 操作结果: 后序递归遍历T */171 void PostOrderTraverse(BiTree T)172 {173     if(T==NULL)174         return;175     PostOrderTraverse(T->lchild); /* 先后序遍历左子树  */176     PostOrderTraverse(T->rchild); /* 再后序遍历右子树  */177     printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */178 }179 180 181 int main()182 {183     int i;184     BiTree T;185     TElemType e1;186     InitBiTree(&T);187 188     189     StrAssign(str,"ABDH#K###E##CFI###G#J##");190 191     CreateBiTree(&T);192 193     printf("构造空二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n",BiTreeEmpty(T),BiTreeDepth(T));194     e1=Root(T);195     printf("二叉树的根为: %c\n",e1);196 197     printf("\n前序遍历二叉树:");198     PreOrderTraverse(T);199     printf("\n中序遍历二叉树:");200     InOrderTraverse(T);201     printf("\n后序遍历二叉树:");202     PostOrderTraverse(T);203     ClearBiTree(&T);204     printf("\n清除二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n",BiTreeEmpty(T),BiTreeDepth(T));205     i=Root(T);206     if(!i)207         printf("树空,无根\n");208     209     return 0;210 }

 

转载于:https://www.cnblogs.com/gltks/p/10588262.html

你可能感兴趣的文章
Module 的加载实现
查看>>
Android视频录制从不入门到入门系列教程(四)————Camera Parameter
查看>>
1-7个人博客
查看>>
探偵ガリレオ 燃えるまで
查看>>
利用PHP的debug_backtrace函数,实现PHP文件权限管理、动态加载
查看>>
设置 MyEclipse 启动时提示选择的工作空间
查看>>
字符串
查看>>
FCoE BB6 相关学习笔记
查看>>
js判断对象是否为空对象的几种方法
查看>>
对数器的使用
查看>>
C语言关系运算符
查看>>
重构手法之简化函数调用【3】
查看>>
HashMap存入大量数据是否要预定义存储空间
查看>>
android-effect
查看>>
类的继承
查看>>
PyCharm 安装
查看>>
Ansible 管理任务计划
查看>>
iteritems()
查看>>
HDOJ 4607 - Park Visit
查看>>
服务器相对路径Nginx入门之二
查看>>