【ADT】链表的基本C语言实现

什么是抽象数据类型?
首先,这一概念是软件开发人员在力求编写的代码健壮、易维护且可以复用的过程中产生的。
英文是AbstractData Type。有人将其比作“抽象”的墙壁,“它将接口和实现明确分开,所以用户只看到接口,因此不需要参与实现。”构建者则着力实现ADT接口。ADT成为了双方的契约,这使得代码更容易维护。

接口:接口是把公共的方法和属性组合起来以封装特定功能的一个集合。

创建linked list.h头文件

 1 #ifndef LIST_H_
 2 #define LIST_H_
 3 #include <stdbool.h>
 4 #define TSIZE 45
 5
 6 typedef struct book{ // 建立包含元素属性的item结构体
 7     char title[TSIZE];
 8     int rating;
 9 }Item;
10
11 typedef struct node { // 链表的节点,包含item各项属性以及一个用来存放下一项地址的指针(链表链接的关键)
12     Item item;
13     struct node*next;
14 }Node;
15 typedef Node * List;
16
17 void InitList(List * plist);
18 bool ListisEmpty(const List * plist);
19 bool ListisFull(const List * plist);
20 unsigned int ListItemCount(const List * plist);
21 bool AddItem(Item item, List * plist);
22 void Traverse(const List * plist, void(*pfun)(Item item));
23 void EmptyTheList(List * plist);
24
25 #endif

功能函数的定义

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include "list.h"
 4 static void CopyToNode(Item item, Node * pnode) // 拷贝数据
 5 {
 6     pnode->item = item;
 7 }
 8 void InitList(List * plist) // 初始化链表为空
 9 {
10     *plist = NULL;
11 }
12
13 bool ListisEmpty(const List * plist)  // 检查链表是否为空
14 {
15     return *plist == NULL ? true : false;
16 }
17 bool ListisFull(const List * plist)  // 检查链表是否已满
18 {
19     Node * pt;
20     pt = (Node *)malloc(sizeof(Node));
21     return pt == NULL ? true : false;
22 }
23 unsigned int ListItemCount(const List * plist)
24 {
25     unsigned int count = 0;
26     Node * pnode = *plist;
27     while (pnode != NULL)
28     {
29         ++count;
30         pnode = pnode->next;
31     }
32     return count;
33 }
34 bool AddItem(Item item, List * plist) // 在链表结尾添加新的项
35 {
36     Node * pnew; // 申请一个新的节点
37     Node * scan = *plist;
38     pnew = (Node *)malloc(sizeof(Node)); // 给新节点申请空间
39     if (pnew == NULL) return false; // 申请失败,返回false
40     CopyToNode(item, pnew); // 把item的内容复制到新节点中
41     pnew->next = NULL; // 将新节点的next指针设置为NULL,表示这一节点为当前的末尾项
42     if (scan == NULL) // 如果当前是空表,则将新节点设置为表的首项
43         *plist = pnew;
44     else
45     {
46         while (scan->next != NULL) //找到当前表中的末尾节点
47             scan = scan->next;
48         scan->next = pnew; //将新节点的地址保存在末尾节点的next成员里(即给链表添加了一个新的项)
49     }
50     return true;
51 }
52 void Traverse(const List * plist, void(*pfun)(Item item)) // 将某函数作用于链表的每一节点
53 {
54     Node * pnode = *plist; // 将节点指向开头
55     while (pnode != NULL)
56     {
57         (*pfun)(pnode->item);
58         pnode = pnode->next;
59     }
60 }
61 void EmptyTheList(List * plist) // 清空链表
62 {
63     Node * psave; // 用来保存当前清除项的下一节点的地址
64     while (*plist != NULL)
65     {
66         psave = (*plist)->next;
67         free(*plist);
68         *plist = psave;
69     }
70 }

用户接口:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include "list.h"
 5 void showmovies(Item item);
 6 char * s_gets(char * st, int n);
 7
 8 int main(void)
 9 {
10     List book;
11     Item temp;
12
13     InitList(&book);
14     if (ListisFull(&book))
15     {
16         fprintf(stderr, "No memory available\n");
17         exit(EXIT_FAILURE);
18     }
19
20     puts("Enter first book title:");
21     while (s_gets(temp.title, TSIZE) != NULL&&
22         temp.title[0] != ‘\0‘)
23     {
24         puts("Enter your rating<0-10>:");
25         scanf("%d", &temp.rating);
26         while (getchar() != ‘\n‘)
27             continue;
28         if (AddItem(temp, &book) == false)
29         {
30             fprintf(stderr, "Problem allocating memory\n");
31             break;
32         }
33         if (ListisFull(&book))
34         {
35             puts("The list is now full.\n");
36             break;
37         }
38         puts("Enter next book title(empty line to stop):");
39     }
40
41     if (ListisEmpty(&book))
42         printf("No data entered.\n");
43     else {
44         printf("Here is the movies list:\n");
45         Traverse(&book, showmovies);
46     }
47     printf("You entered %d movies.\n", ListItemCount(&book));
48
49     EmptyTheList(&book);
50     printf("Bye\n");
51
52     return 0;
53 }
54 void showmovies(Item item)
55 {
56     printf("book: %s Rating:%d\n", item.title, item.rating);
57 }
58 char * s_gets(char * st, int n)
59 {
60     char * ret_val;
61     char * find;
62     ret_val = fgets(st, n, stdin);
63     if (ret_val)
64     {
65         find = strchr(st, ‘\n‘);
66         if (find)
67             *find = ‘\0‘;
68         else
69             while (getchar() != ‘\n‘)
70                 continue;
71     }
72     return ret_val;
73 }
时间: 2024-09-30 18:55:25

【ADT】链表的基本C语言实现的相关文章

数据结构—单链表(类C语言描写叙述)

单链表 1.链接存储方法 链接方式存储的线性表简称为链表(Linked List). 链表的详细存储表示为: ① 用一组随意的存储单元来存放线性表的结点(这组存储单元既能够是连续的.也能够是不连续的) ② 链表中结点的逻辑次序和物理次序不一定同样.为了能正确表示结点间的逻辑关系,在存储每一个结点值的同一时候,还必须存储指示其后继结点的地址(或位置)信息(称为指针(pointer)或链(link)) 注意: 链式存储是最经常使用的存储方式之中的一个.它不仅可用来表示线性表.并且可用来表示各种非线性

链表源代码(C语言实现)

源代码(C语言实现) ①.构造链表节点 typedef struct Node    //一个单独的节点                   {                         int data;//数据域                         struct Node * pNext;//指针域                    }NODE,* PNODE; ②.链表的初始化 PNODE init_list()                  {         

静态链表----数据结构(C语言版) 算法2.17 心得

今天学习了数据结构中的静态链表,刚开始有些语句不能理解,研究了大半天终于想通了.记录于此留待以后查看,同时,对于同样对静态链表有些许不理解的人一点启发.文章中难免有理解上的问题,请指正.下面进入正文. 一.静态链表结构 静态链表可以在不设"指针"类型的高级程序设计语言中使用链表结构.静态链表如下所示:   首先,了解一下静态链表.静态链表中跟单链表类似,包含有很多结点,第i个结点中有包括数据space[i].data,和游标cur,游标space[i].cur的值为下一个结点的数组下标

链表的基本操作java语言实现

package com.baorant; public class JavaDemo { public static void main(String[] args) { LinkList linkList = new LinkList(); linkList.addFirstNode(20); linkList.addFirstNode(21); linkList.addFirstNode(19); // 19,21,20 linkList.add(1, 22); // 19,22,21,20

链表之循环单链表(用C语言描述)

上回说到建立链表的三种形式,分别是头插法,尾插法,和尾插法MAX?? ??下面讲一下循环单链表?? 循环单链表,字面意思,就是单链表循环了起来,尾节点在输入结束后不会指向NULL,而是指向了头节点head 酱紫,链表就循环了起来 下面是代码实现 #include <stdio.h> #include <stdlib.h> typedef char datatype; typedef struct node { datatype data; struct node *next; in

链表栈的C语言实现

#ifndef _CONST_H_#define _CONST_H_ #include <stdio.h>#include <stdlib.h> typedef enum { False = 0, True,}Bool; typedef int ElemType; #define QUEUE_MAX_SIZE 10 #define STACK_INIT_SIZE 10#define STACK_INCREMENT_SIZE 2 #define Null ((void *)0) ty

[PAT] 02-线性结构2 Reversing Linked List(单向链表的逆转) - C语言实现

今天突然想起自己的cnblog有差不多一年没更了??放一道很久前做的也写好了很久但是一直忘记发布的题.如果有不同的算法欢迎分享~ [PAT]02-线性结构2 Reversing Linked List   (25分) Given a constant KK and a singly linked list LL, you are supposed to reverse the links of every KK elements on LL. For example, given LL bein

链表实现队列 c语言

#include<stdio.h> #include<malloc.h> #include<stdlib.h> #define Data_Type int typedef struct Node{ Data_Type data; struct Node * pNext; }NODE,*PNODE; typedef struct LinkQueue{ //first node PNODE front; //lash node PNODE rear; }LINKQUEUE,

深入浅出数据结构C语言版(5)——链表的操作

上一次我们从什么是表一直讲到了链表该怎么实现的想法上:http://www.cnblogs.com/mm93/p/6574912.html 而这一次我们就要实现所说的承诺,即实现链表应有的操作(至于游标数组--我决定还是给它单独写个博文比较好~). 那么,我们的过程应该是怎么样的呢?首先当然是分析需要什么操作,然后再逐一思考该如何实现,最后再以代码的形式写出来. 不难发现,我们希望链表能支持的(基础,可以由此延伸)操作就是: 1.给出第n个元素 2.在第n个元素的后面插入一个元素(包含在最后一个