[关闭]
@quinn 2015-03-20T01:28:44.000000Z 字数 4285 阅读 590

抽象数据类型总结:复数 adt 和 FIFO 队列adt

数据结构


定义:抽象数据类型(abstract data type, ADT)是指”“通过接口进行访问的数据类型。我们将那些使用ADT的程序叫做客户,将那些确定数据类型的程序叫做实现。
客户程序除了通过接口中提供的那些操作外,并不访问任何数据值。数据的表示和操作都在接口的实现里,和客户完全分离。

数据结构、数据类型和抽象数据类型

   数据结构、数据类型和抽象数据类型,这3个术语在字面上虽不同但相近,反映出它们在含义上既有区别又有联系。       
  1. 数据结构

    数据结构是计算机科学与技术领域常用的术语。它用来反映一个数据的内部构成,即一个数据由哪些成分数据构成,以什么方式构成,呈什么结构。逻辑上的数据结构反映成分数据之间的逻辑关系,物理上的数据结构反映成分数据在计算机内的存储安排。数据结构是数据存在的形式。

  2. 数据类型

    数据是按照数据结构分类的,具有相同数据结构的数据属同一类。同一类数据的全体称为数据类型。在程序设计高级语言中,数据类型用来说明一个数据在数据分类中的归属。它是数据的一种属性。这个属性限定了该数据的变化范围。为了解题的需要,根据数据结构的种类,高级语言定义了一系列的数据类型。不同的高级语言所定义的数据类型不尽相同。

  3. 抽象数据类型

    抽象数据类型的含义可理解为数据类型的进一步抽象。即把数据类型和数据类型上的运算捆在一起,进行封装。引入抽象数据类型的目的是把数据类型的表示和数据类型上运算的实现与这些数据类型和运算在程序中的引用隔开,使它们相互独立。对于抽象数据类型的描述,除了必须描述它的数据结构外,还必须描述定义在它上面的运算(过程或函数)。抽象数据类型上定义的过程和函数以该抽象数据类型的数据所应具有的数据结构为基础。

抽象数据类型的举例:

1.复数的一级ADT

完整工程下载:传送门--vs2012 dev.

复数的一级ADT接口

句柄定义为指向结构体的一个指针,该结构体只有命名标志,没有明确定义。客户程序可以以任意方式使用这个句柄,但是不能通过改变指针指向访问结构体中的一个域,这是因为它没有这些域的任何名字。

  1. //complex.h
  2. typedef struct complex *Complex; //隐藏数据表示,不提供具体的说明
  3. Complex COMPLEXinit(float , float);
  4. float Re(Complex);
  5. float Im(Complex
  6. Complex COMPLEXmult(Complex, Complex);
  7. Complex COMPLEXadd(Complex, Complex);
  8. void showComplex(Complex );

复数的一级ADT实现

它包括了结构定义和函数实现。对象是指向结构的指针,因而我们使指针指向这个链域。

  1. //complex.cpp
  2. /************************************************************************/
  3. /* 复数的一级ADT:包含结构定义和函数实现 */
  4. /************************************************************************/
  5. #include "Complex.h"
  6. #include <malloc.h>
  7. #include <stdio.h>
  8. struct complex
  9. {
  10. float Re;
  11. float Im;
  12. };
  13. //初始化
  14. Complex COMPLEXinit( float re, float im)
  15. {
  16. Complex t = (Complex)malloc(sizeof(t));
  17. t->Re = re;
  18. t->Im = im;
  19. return t;
  20. }
  21. //取实部
  22. float Re(Complex z)
  23. {
  24. return z->Re;
  25. }
  26. //取虚部
  27. float Im(Complex z)
  28. {
  29. return z->Im;
  30. }
  31. //复数乘
  32. Complex COMPLEXmult( Complex a, Complex b)
  33. {
  34. return COMPLEXinit(Re(a) * Re(b) - Im(a) * Im(b),
  35. Re(a) * Im(b) + Im(a) * Re(b));
  36. }
  37. //复数加
  38. Complex COMPLEXadd(Complex a, Complex b)
  39. {
  40. return COMPLEXinit( Re(a) + Re(b),
  41. Im(a) + Im(b));
  42. }
  43. void showComplex(Complex z)
  44. {
  45. printf("%3.1f + %3.1f*i\n", Re(z), Im(z));
  46. }

客户驱动程序(测试)

  1. //main.cpp
  2. #include <stdio.h>
  3. #include<stdlib.h>
  4. #include "Complex.h"
  5. int main(int argc, char *argv[])
  6. {
  7. Complex c1, c2, c3, c4;
  8. c1 = COMPLEXinit(1, 1);
  9. c2 = COMPLEXinit(1, -1);
  10. c3 = COMPLEXmult(c1, c2);
  11. c4 = COMPLEXadd(c1, c2);
  12. showComplex(c1);
  13. showComplex(c2);
  14. showComplex(c3);
  15. showComplex(c4);
  16. system("pause");
  17. return 0;
  18. }

运行结果

这里写图片描述

2. FIFO队列ADT

完整工程下载:传送门--vs2012 dev.
修改为单一对象提供FIFO队列实现(传送门)的代码,使之为对象句柄提供实现。

队列客户程序:随机把N个项赋给M个FIFO队列中的一个,然后逐个删除队列中的项

队列ADT接口

  1. //queue.h
  2. /************************************
  3. 队列的一级ADT接口
  4. ************************************/
  5. typedef int Item;
  6. typedef struct Node Node;//隐藏数据表示,使客户不能直接访问
  7. typedef struct queue* Queue;
  8. Node* NewNode(Item , Node* ); // Next为插入的后一节点
  9. Queue QueueInit(int );
  10. int QueueIsEmpty(Queue );
  11. void QueuePut(Queue , Item );
  12. Item QueueGet(Queue );

队列ADT实现

  1. //queue.cpp
  2. /*************************************************************
  3. FIFO队列的ADT实现
  4. 功能:先进先出队列的链表形式实现:Init、Put、Get操作
  5. 说明: 从头部Get,从尾部Put
  6. 时间: 2015/02/09
  7. 作者: quinn
  8. **************************************************************/
  9. #include<stdio.h>
  10. #include<stdlib.h>
  11. #include "queue.h"
  12. struct Node //节点结构
  13. {
  14. Item item;
  15. Node* next;
  16. };
  17. struct queue
  18. {
  19. Node* head;
  20. Node* tail;
  21. };
  22. //新建一个节点
  23. Node* NewNode(Item item, Node* Next) // Next为插入的后一节点
  24. {
  25. Node* x = (Node*)malloc(sizeof(*x));//被插入的节点
  26. x->item = item;
  27. x->next = Next;
  28. return x;
  29. }
  30. //队列初始化
  31. Queue QueueInit(int maxN)
  32. {
  33. Queue q = (Queue)malloc(sizeof(q));
  34. q->head = NULL;
  35. return q;
  36. }
  37. //判断队列是否为空
  38. int QueueIsEmpty(Queue q)
  39. {
  40. return (q->head == NULL);
  41. }
  42. //put操作
  43. void QueuePut(Queue q, Item item)
  44. {
  45. if(QueueIsEmpty(q))
  46. {
  47. q->head = (q->tail = NewNode(item, q->head));
  48. }
  49. else
  50. {
  51. q->tail->next = NewNode(item, q->tail->next);
  52. q->tail =q->tail->next;
  53. }
  54. printf("Put: %d\n", item);
  55. }
  56. //get操作
  57. Item QueueGet(Queue q)
  58. {
  59. if(q->head == NULL)
  60. {
  61. printf("序列为空!\n");
  62. return -1;
  63. }
  64. Item firstItem = q->head->item;//序列的头元素
  65. Node* tmpNode = q->head;
  66. q->head = q->head->next;
  67. free(tmpNode);
  68. return firstItem;
  69. }

客户驱动程序

  1. //main.cpp
  2. /*********************************************
  3. 队列客户驱动程序
  4. 功能:随机把N个项赋给M个FIFO队列中的一个,然后逐个删除队列中的项
  5. 其他:使用对象句柄带有ADT对象的复合数据结构;每个队列都对应自己的head和tail
  6. 时间: 2015/02/09
  7. 作者: quinn
  8. *********************************************/
  9. #include "queue.h"
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #define M 10
  13. int main(int argc, char *argv[])
  14. {
  15. int N = atoi(argv[1]);
  16. Queue q[M];
  17. //初始化
  18. for (int i = 0; i < M; i++)
  19. {
  20. q[i] = QueueInit(N);
  21. }
  22. //put
  23. for (int j = 0; j < N; j++)
  24. {
  25. QueuePut(q[rand() % M], j);
  26. }
  27. //get
  28. for (int i = 0; i < M; i++)
  29. {
  30. while (!QueueIsEmpty(q[i]))
  31. {
  32. printf("%3d", QueueGet(q[i]));
  33. }
  34. printf("\n");
  35. }
  36. system("pause");
  37. return 0;
  38. }

运行结果

带参数 100 (N = 100项)
这里写图片描述

总结

ADT接口定义用户和实现的一种协议,为他们直接相互通信提供了精确手段。我们可以更改接口的实现方式,但客户程序不受影响。

参考资料:
1. http://jsjedu.hxu.edu.cn/dxjsjjc/kcnr/wlkj/06software/detail/6-3-2.htm#
2. 《算法:C语言实现》 第4章 抽象数据类型

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注