【ADT】链表的基本C语言实现
什么是抽象数据类型?
首先,这一概念是软件开发人员在力求编写的代码健壮、易维护且可以复用的过程中产生的。
英文是AbstractData Type。有人将其比作“抽象”的墙壁,“它将接口和实现明确分开,所以用户只看到接口,因此不需要参与实现。”构建者则着力实现ADT接口。ADT成为了双方的契约,这使得代码更容易维护。
接口:接口是把公共的方法和属性组合起来以封装特定功能的一个集合。
创建linked list.h头文件
#ifndef LIST_H_
#define LIST_H_
#include <stdbool.h>
#define TSIZE 45 typedef struct book{ // 建立包含元素属性的item结构体
char title[TSIZE];
int rating;
}Item; typedef struct node { // 链表的节点,包含item各项属性以及一个用来存放下一项地址的指针(链表链接的关键)
Item item;
struct node*next;
}Node;
typedef Node * List; void InitList(List * plist);
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));
void EmptyTheList(List * plist); #endif
功能函数的定义
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
static void CopyToNode(Item item, Node * pnode) // 拷贝数据
{
pnode->item = item;
}
void InitList(List * plist) // 初始化链表为空
{
*plist = NULL;
} bool ListisEmpty(const List * plist) // 检查链表是否为空
{
return *plist == NULL ? true : false;
}
bool ListisFull(const List * plist) // 检查链表是否已满
{
Node * pt;
pt = (Node *)malloc(sizeof(Node));
return pt == NULL ? true : false;
}
unsigned int ListItemCount(const List * plist)
{
unsigned int count = ;
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; // 申请失败,返回false
CopyToNode(item, pnew); // 把item的内容复制到新节点中
pnew->next = NULL; // 将新节点的next指针设置为NULL,表示这一节点为当前的末尾项
if (scan == NULL) // 如果当前是空表,则将新节点设置为表的首项
*plist = pnew;
else
{
while (scan->next != NULL) //找到当前表中的末尾节点
scan = scan->next;
scan->next = pnew; //将新节点的地址保存在末尾节点的next成员里(即给链表添加了一个新的项)
}
return true;
}
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;
}
}
用户接口:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"
void showmovies(Item item);
char * s_gets(char * st, int n); int main(void)
{
List book;
Item temp; InitList(&book);
if (ListisFull(&book))
{
fprintf(stderr, "No memory available\n");
exit(EXIT_FAILURE);
} puts("Enter first book title:");
while (s_gets(temp.title, TSIZE) != NULL&&
temp.title[] != '\0')
{
puts("Enter your rating<0-10>:");
scanf("%d", &temp.rating);
while (getchar() != '\n')
continue;
if (AddItem(temp, &book) == false)
{
fprintf(stderr, "Problem allocating memory\n");
break;
}
if (ListisFull(&book))
{
puts("The list is now full.\n");
break;
}
puts("Enter next book title(empty line to stop):");
} if (ListisEmpty(&book))
printf("No data entered.\n");
else {
printf("Here is the movies list:\n");
Traverse(&book, showmovies);
}
printf("You entered %d movies.\n", ListItemCount(&book)); EmptyTheList(&book);
printf("Bye\n"); return ;
}
void showmovies(Item item)
{
printf("book: %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;
}
【ADT】链表的基本C语言实现的更多相关文章
- 由链表初始化看C语言的二级指针
先来看C语言创建链表.插入节点和遍历链表的一段代码: #include <stdio.h> #include <stdlib.h> typedef int ElemType; ...
- 链表的创建(C语言实现)
学习链表之前,我们要知道为什么要引入链表. C语言中的数组使用之前,我们必须要定义数组的大小.但是当我们不知道数据个数(或者很大)时,定义数组大小就成了一个困扰,而且对于这么多数据的处理也会很麻烦.所 ...
- 数据结构—单链表(类C语言描写叙述)
单链表 1.链接存储方法 链接方式存储的线性表简称为链表(Linked List). 链表的详细存储表示为: ① 用一组随意的存储单元来存放线性表的结点(这组存储单元既能够是连续的.也能够是不连续的) ...
- 链表源代码(C语言实现)
源代码(C语言实现) ①.构造链表节点 typedef struct Node //一个单独的节点 { int ...
- 不带头结点的单链表(基于c语言)
本篇文章的代码大多使用无头结点的单链表: 相关定义: #include <stdio.h> #include <stdlib.h> #include <assert.h& ...
- 链表的实现(Java语言描述)
代码如下: public interface ListInterface<T> { public T getElem(int i); public boolean insertElem(i ...
- 链表数据结构(C/C++语言实现)
注意:没有使用malloc和free:加了一个头文件,用于清屏和暂停:还有就是一个错误特别容易被忽略,那就是主函数中声明了LinkList p,然后就直接创建链表,忘了给p分配空间.一定要先初始化链表 ...
- 1025 反转链表 (25 分)C语言
题目描述 给定一个常数K以及一个单链表L,请编写程序将L中每K个结点反转.例如:给定L为1→2→3→4→5→6,K为3,则输出应该为 3→2→1→6→5→4:如果K为4,则输出应该为4→3→2→1→5 ...
- PTA 学生成绩链表处理(C语言)
本题要求实现两个函数,一个将输入的学生成绩组织成单向链表:另一个将成绩低于某分数线的学生结点从链表中删除. 函数接口定义: struct stud_node *createlist(); struct ...
随机推荐
- css-div下内容垂直居中
1.多行行文字在固定高度的div中垂直居中,只兼容高级浏览器和移动端 .detail { width: 395px; height: 289px; display: -webkit-box; -web ...
- Vrui 增加自定义事件
#include <Vrui/Application.h> #include <GL/GLObject.h> #include <Vrui/Vrui.h> #inc ...
- php 学习之对象
php中怎么实现创建一个对象然后全局都能调用? 在PHP中相当常见的一种情形时,我们只需要创建一个对象一次,然后在我们的整个程序中使用它.一个很好的例子就是smarty变量,一旦被初始化后就可以在任何 ...
- edgerouter bonding
configure set interfaces bonding bond0 mode 802.3ad set interfaces ethernet eth1 bond-group bond0 se ...
- 解决Windows内存问题的两个小工具RamMap和VMMap(这个更牛更好)
来源:http://www.cr173.com/html/13006_1.html .net程序内存监测分配工具(CLR Profiler for .NET Framework 4)官方安装版 类型: ...
- FD.io VPP 技术Neutron VNF vRouter 实现
在OpenStack Neutron中主要有三种网络设备,路由器(Router),负载均衡器(LB)以及VPN,其中Router作为基础网络设备起到连接子网到子网.内网到外网的作用.不同子网之间的访问 ...
- Linux常用命令汇总及使用方法(三)
(1)文件管理命令 ls.ls -l.ll.ls -a ls -a 显示所有文件,包括隐藏文件 ls 列举指定目录下的子目录和文件 ls -l与ll相同 列举指定目录下的子目录和文件的详细信息 tot ...
- 向量空间(Vector Spaces)
向量空间(Vector Spaces) 向量空间又称线性空间,是线性代数的中心内容和基本概念之一.在解析几何里引入向量的概念后,是许多问题的处理变得更为简洁和清晰,在此基础上的进一步抽象化,形成了与域 ...
- event 实现观察者模式
看了一些其他人写的,一下就晕了,还是自己写一个给自己看吧. 用event语法糖实现的观察者,与普通的实现,最大的区别在于,Subject的操作中不会直接触发Observer的Update,而是通过ev ...
- 查看SQL语句执行时间与测试SQL语句性能
查看SQL语句执行时间与测试SQL语句性能 写程序的人,往往需要分析所写的SQL语句是否够优化.是否能提升执行效率,服务器的响应时间有多快,这个时候就需要用到SQL的STATISTICS状态值来查看了 ...