【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 ...
- Angular React 和 Vue的比较
Angular(1&2),React,Vue对比 一 数据流 数据绑定 Angular 使用双向绑定即:界面的操作能实时反映到数据,数据的变更能实时展现到界面. 实现原理: $scope变量中 ...
- Grunt使用教程(限winows)
前提:安装nodejs 一. 打开dos命令窗口,输入命令 "node -v",确认nodejs安装成功 二. 其次,安装grunt-cli (该插件是grunt命令行插件),执行 ...
- js关于setTimeout传参
setTimeout函数有两个参数,都是必须的,一个是要执行的函数,一个是延时的时间 第一个参数: 要执行的函数,一般来说是可以执行的,但是这里遇到一个问题,就是如果变量是个数组的话, 如果数组为nu ...
- 4天html总结
- centos 设置删除提示
centos 设置删除.覆盖提示 相信好多用linux的同学都用过cp这个命令来覆盖文件,但是新建的普通用户不会有任何提示,这时候心里就咯噔一下,赶紧看看新文件的是不是传上去了.如果加上提示,是不是就 ...
- javaWEB总结(16):jsp错误页面的处理
前言 网站上线后,jsp页面上有时会出现不友好的错误信息,我们需要展示给用户更加友好的页面.这时候要用到page标签的errorPage和isErrorPage. errorPage 指定当前页面出现 ...
- hashmap冲突的解决方法以及原理分析:
在Java编程语言中,最基本的结构就是两种,一种是数组,一种是模拟指针(引用),所有的数据结构都可以用这两个基本结构构造,HashMap也一样.当程序试图将多个 key-value 放入 HashMa ...
- iOS开发tableview二级联动的细节实现中注意的细节总结
首先说网络慢带来的数据显示问题 可以通过判断请求参数是否一致来刷新tableview. SJBCategaryModel * categaryModel = self.categarys[Catega ...
- ubuntu 禁用快捷键
System Settings > Keyboard > Shortcuts 点击要禁用的快捷键,按键盘"Backspace"键,就可以禁用了