指针指的是用于存储内存地址的变量;物理内存以字节为单位进行数据存储的;栈是一种后入先出(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 do 116 { 117 /* scanf("%d",&d); */ 118 d=i+100; 119 if(d==-1) 120 break; 121 i++; 122 EnQueue(&Q,d); 123 }while(i1); 124 125 printf("队列长度为: %d\n",QueueLength(Q)); 126 printf("现在队列空否?%u(1:空 0:否)\n",QueueEmpty(Q)); 127 printf("连续%d次由队头删除元素,队尾插入元素:\n",MAXSIZE); 128 for(l=1;l<=MAXSIZE;l++) 129 { 130 DeQueue(&Q,&d); 131 printf("删除的元素是%d,插入的元素:%d \n",d,l+1000); 132 /* scanf("%d",&d); */ 133 d=l+1000; 134 EnQueue(&Q,d); 135 } 136 l=QueueLength(Q); 137 138 printf("现在队列中的元素为: \n"); 139 QueueTraverse(Q); 140 printf("共向队尾插入了%d个元素\n",i+MAXSIZE); 141 if(l-2>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 else 103 return TRUE; 104 } 105 106 #define ClearBiTree DestroyBiTree 107 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 else 117 i=0; 118 if(T->rchild) 119 j=BiTreeDepth(T->rchild); 120 else 121 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 else 131 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 }