您的位置:首页 > 编程语言

抽象数据类型(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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据 编程语言