抽象数据类型(ADT)
2017-08-07 20:08
309 查看
抽象数据类型(ADT)
理论基础
定义新的类型
什么是类型?类型特指两类信息:属性和操作。假设要定义一个新的数据类型:
首先,必须提供存储数据的方法,例如设计一个结构。
其次,必须提供操控数据的方法。
计算机科学领域已开发了一种定义新类型的好方法,用3个步骤完成抽象到具体的过程。
提供类型属性和相关操作的抽象描述。这些描述既不能依赖特定的实现,也不能依赖特定的编程语言。这种正式的抽象描述被称为抽象数据类型(ADT)。
开发一个实现ADT的编程接口。也就是说,指明如何储存数据和执行所需操作的函数。例如在C中,可以提供结构定义和操控该结构的函数原型。这些作用于用户定义类型的函数相当于作用于C基本类型的内置运算符。需要使用该新类型的程序员可以使用这个接口进行编程。
编写代码实现接口。这一步至关重要,但是使用该新类型的程序员无需了解具体的实现细节。
实现过程
建立抽象
以简单电影项目为例,所需的是一个链表数据类型,每一项包含电影名和评级。所需的操作是把新项添加到链表的末尾和显示链表中的内容。链表的属性:
能储存一系列的项,并按照一定方式排列;
链表类型应该提供一些有用的操作。
链表一些有用的操作:
初始化一个空链表;
在链表末尾添加一个新项;
确定链表是否为空;
确定链表是否已满;
确定链表的项数;
访问链表的每一项执行某些操作,如显示该项。
对于该电影项目而言,暂时不需要其他操作。但是一般的链表还应包含以下操作:
在链表的任意位置插入一个项;
移除链表中的一个项;
在链表中检索一个项(不改变链表);
用另一个项替换链表中的一个项。
最后该类型总结如下:
建立接口
list.h接口头文件:/* list.h -- header file for a simple list type */ #ifndef LIST_H_ #define LIST_H_ #include <stdbool.h> /* 特定程序的声明 */ #define TSIZE 45 //储存电影名的数组大小 struct film { char title[TSIZE]; int rating; }; /* 一般类型定义 */ typedef struct film Item; typedef struct node { Item item; struct node * next; } Node; typedef Node * List; //List是指向Node类型的指针 /* 函数原型 */ void InitializeList(List * plist); //plist是指向List类型的指针 bool ListIsEmpty(const List *plist); bool ListIsFull(const List *plist); unsigned int ListItemCount(const List *plist); bool AddItem(Item item, List * plist); void Traverse (const List *plist, void (* pfun)(Item item) );//pfun是指向无返回值、参数为Item类型的函数的指针 void EmptyTheList(List * plist); #endif
使用接口
使用这个接口编写程序,但是不必知道具体细节。伪代码方案:
创建一个List类型的变量。 创建一个Item类型的变量。 初始化链表为空。 当链表未满且有输入时: 把输入读取到Item类型的变量中。 在链表末尾添加项。 访问链表中的每个项并显示他们。
films.c使用ADT风格的链表
#include<stdio.h> #include<stdlib.h> //提供exit()的原型 #include"list.h" //定义Item、List void showmovies(Item item); char * s_gets(char *st, int n); int main(void) { List movies; int count; Item temp; /* 初始化 */ InitializeList(&movies); if (ListIsFull(&movies)) { fprintf(stderr, "No memory available!\n"); exit(1); } /* 获取用户输入并储存 */ puts("Enter first moive title"); while (s_gets(temp.title, TSIZE) != NULL && temp.title[0] != '\0') { puts("Enter your rating <1-10>:"); scanf("%d", &temp.rating); while (getchar() != '\n') continue; if (AddItem(temp,&movies) == false) { fprintf(stderr,"Problem allocating memory.\n"); break; } if (ListIsFull(&movies)) { fprintf(stderr, "The list is now full.\n"); break; } puts("Enter the next title:"); } /* 显示 */ if (ListIsEmpty(&movies)) printf("No data entered.\n"); else { printf("Here is the moive list:\n"); Traverse(&movies, showmovies); } printf("You entered %d moives.\n", ListItemCount(&movies)); /* 清理 */ EmptyTheList(&movies); puts("88"); return 0; } void showmovies(Item item) { printf("Moive: %s Rating: %d\n",item.title, item.rating); } char * s_gets(char *st, int n) { char *ret_val; char *find; ret_val = fgets(st, n, stdin); if (ret_val) { find = strchr(st,'\n'); if (find) *find = '\0'; else while (getchar() != '\n') continue; } return ret_val; }
实现接口
list.c实现文件//支持链表操作的函数 #include<stdio.h> #include<stdlib.h> #include"list.h" //局部函数原型 static void CopyToNode(Item item, Node * pnode);//内部链接,只在文件内生效 //接口函数 //把链表设置为空 void InitializeList(List * plist)//plist是指向List的指针,*plist是指向Node的指针 { *plist = NULL; } bool ListIsEmpty(const List * plist) { if (*plist == NULL) return true; else return false; } bool ListIsFull(const List * plist) { Node * pt; bool full; pt = (Node *)malloc(sizeof(Node)); if (pt == NULL) full = true; else full = false; free(pt); return full; } unsigned int ListItemCount(const List * plist) { unsigned int count = 0; Node * pnode = *plist; while (pnode != NULL) { ++count; pnode = pnode->next; } return count; } bool AddItem(Item item, List * plist) { Node * pnew; Node * scan = *plist; pnew = (Node *)malloc(sizeof(Node)); if(pnew == NULL) return false; CopyToNode(item, pnew); pnew->next = NULL; if (scan == NULL) *plist = pnew; else { while(scan->next != NULL) scan = scan->next; scan->next = pnew; } return true; } //访问每个节点并执行pfun指向的函数 void Traverse(const List * plist, void (*pfun)(Item item)) { Node * pnode = *plist; while (pnode != NULL) { (*pfun)(pnode->item); pnode = pnode->next; } } void EmptyTheList(List * plist) { Node * psave; while (*plist != NULL) { psave = (*plist)->next; free(*plist); *plist = psave; } } static void CopyToNode(Item item, Node * pnode) { pnode->item = item; }
4000
相关文章推荐
- C语言ADT(抽象数据类型编程)
- 栈的抽象数据类型(abstract data type,ADT)
- 抽象数据类型ADT之栈的构建
- C语言ADT(抽象数据类型编程) (含Demo演示文件)
- 第七话:抽象数据类型ADT
- C编程思想之抽象数据类型(ADT)(四)
- 抽象数据类型总结:复数 adt 和 FIFO 队列adt
- java算法:抽象数据类型ADT
- 数据结构(scheme) -- 抽象数据类型(ADT) -- 栈
- 不要忽视抽象数据类型(ADT)
- 抽象数据类型(ADT)
- c语言的抽象数据类型(ADT)
- 抽象数据类型(ADT) 双链表实现
- C编程思想之抽象数据类型(ADT)(五)实例演练
- 数据结构(scheme) -- 抽象数据类型(ADT) -- 二叉查找树
- 抽象数据类型定义(ADT)
- C++抽象数据类型(ADT Abstract Data Type)简述
- ADT描述规范 (abstract data type)抽象数据类型
- 数据结构(scheme) -- 抽象数据类型(ADT) -- 4000 队列
- 数据结构(scheme) -- 抽象数据类型(ADT) -- 图