单链表ADT
本博客第一篇学术性博客,所以还是写点什么东西;
首先这篇博客以及以后的博客中的代码尽量百分之90是自己写过的;
可能有部分图片和代码是我认为别人更好的故摘抄下来,
本人三观正确,所以一定会表明来源;
—————————华丽的分割线——————————————
参考书籍——《数据结构于算法分析(C语言描述)》
链表是最基本的数据结构之一,当我们学习完C语言后就会涉及到一点点链表的知识;
本篇博客主要记录链表的一些简单思路以及它的一些主要例程;
按照c的约定我们先将链表的函数原型以及一些typedef定义都放在一个Lish.h头文件里
List.h:
#ifndef LIST_H
#define LIST_H typedef char ElementType; struct Node;
typedef struct Node *PtrToNode;
typedef PtrToNode Position;
typedef PtrToNode List; List MakeEmpty(List L);
int IsLast(Position P, List L);
int IsEmpty(List L);
Position FindPrevious(List L, ElementType x);
Position Find(List L, ElementType x);
void Delete(List L, ElementType x);
void Insert(List L, ElementType x, Position P);
void InsertToTail(List L, ElementType x);
void InsertToHead(List L, ElementType x);
void PrintList(List L);
void DeleteList(List L);
void Reverse(List L); #endif
本篇中的代码所建立的链表都是带有头节点的链表,而使用表头属于个人习惯,我们不再这里做深究
下面的函数尽量满足ADT的想法,没有写CreateList函数是因为该函数功能是对一个已经创建好了的链表的操作而不是一个纯练习的文件,这是个人对此的理解如有更好的解释请大方私信我!谢谢!
添加了两个Insert函数分别是InsertToTail和InsertToHead,从字面上来看就是尾插法和头插法,考虑到M.A.W的Insert例程需要传入位置P,而此举往往很麻烦,于是加上了一个直接插入到尾部和头部的函数
使整个ADT的想法更加完善。
操作图示:

这里主要将链表的一些主要例程写出来,并将这些函数封装在一个.c文件里增强复用性!
SingleLinkedList.c:
#include"List.h"
#include<stdio.h>
#include<stdlib.h> struct Node{
ElementType Element;
PtrToNode Next;
}; List MakeEmpty(List L)
{
if(NULL != L)
{
L->Next = NULL;
}
return L;
} int IsLast(Position P, List L)//L is unused
{
return P->Next == NULL;
} int IsEmpty(List L)
{
return L->Next == NULL;
} Position FindPrevious(List L, ElementType x)
{
Position P;
P = L;
while(P->Next && P->Next->Element != x)
P = P->Next;
return P;
} Position Find(List L, ElementType x)
{
Position P;
P = L->Next;
while(P && P->Element != x)
P = P->Next;
return P;
} void Delete(List L, ElementType x)
{
Position Pre, Tmpcell; Pre = FindPrevious(L, x);//we need find the previous of deleted element
if(!IsLast(Pre, L))
{
Tmpcell = Pre->Next;
Pre->Next = Tmpcell->Next;
free(Tmpcell);
}
} //we insert the element after the position p
void Insert(List L, ElementType x, Position P)
{
Position NewCell;
TmpCell = (List)malloc(sizeof(struct Node));
if(NULL == NewCell)
printf("No space for allocation!!");
else
{
NewCell->Element = x;
NewCell->Next = P->Next;
P->Next = NewCell;
}
}
//插入链表尾部(尾插法)
void InsertToTail(List L, ElementType x)
{
Position Last, NewCell;
Last = L;
/*遍历链表找到最后一个结点*/
while(NULL != Last->Next)
Last = Last->Next;
Insert(L, x, Last);
}
//插入链表头部(头插法)
void InsertToHead(List L, ElementType x)
{
Insert(L, x, L);
} void PrintList(List L)
{
PtrToNode Tmp;
Tmp = L->Next;
while(Tmp->Next)
{
printf("%c-", Tmp->Element);
Tmp = Tmp->Next;
}
printf("%c\n", Tmp->Element);
} void DeleteList(List L)
{
Position Tmp, P;
P = L->Next;
L->Next = NULL;
while(P != NULL)
{
Tmp = P->Next;
free(P);
P = Tmp;
}
free(L);
} void Reverse(List L)
{
Position CurrentPos, NextPos, PreviousPos; CurrentPos = L->Next;//当前单链表的第一个节点
PreviousPos = NULL;//指向新链表的第一个节点,假设开始为空
while(CurrentPos != NULL)
{
NextPos = CurrentPos->Next;//取得当前节点的下一个节点位置
CurrentPos->Next = PreviousPos;//当前节点连接成新的链表
PreviousPos = CurrentPos;
CurrentPos = NextPos;//遍历到下一个节点
}
L->Next = PreviousPos;//哑元节点连接新链表的头节点
}
//与上述思想差不多,主要在返回上
/*Asumming(假如)is no header and L is not empty*/
//List Reverse(List L)
//{
// Position CurrentPos, NextPos, PreviousPos;
//
// CurrentPos = L;
// PreviousPos = NULL;
// while(CurrentPos != NULL)
// {
// NextPos = CurrentPos->Next;
// CurrentPos->Next = PreviousPos;
// PreviousPos = CurrentPos;
// CurrentPos = NextPos;
// }
// return PreviousPos;
//}
//下面是复杂记忆写法
//void Reverse(List L)//含有头节点
//{
// Position Tmp, P;
// Tmp = L->Next;
// L->Next = NULL;
// while(Tmp != NULL)
// {
// P = Tmp->Next;
// Tmp->Next = L->Next;
// L->Next = Tmp;
// Tmp = P;
// }
//}
//List Reverse(List L)//不含头节点
//{
// PtrToNode Tmp, P;
// P = L;
// L = NULL;
// while(P != NULL){
// Tmp = P->Next;
// P->Next = L;
// L = P;
// P = Tmp;
// }
// return L;
//}
下面贴出自己写的一组测试代码
Test.c:
#include"List.h"
#include<stdio.h>
#include<stdlib.h> int main()
{
ElementType Elem, De, PreElem, Ins;
Position Tmp;
List L;
L = (List)malloc(sizeof(struct Node));
if(NULL == L)
printf("Allocation failure!!!");
L = MakeEmpty(L);
printf("Please enter the element until the end of '#':");
while((Elem = getchar()) != '#')
{
InsertToTail(L, Elem);
}
getchar();
PrintList(L);
//删除并输出
printf("Please enter the element you want to delete:");
scanf("%c", &De);
getchar(); Delete(L, De);
PrintList(L);
//插入并输出
printf("After which element do you want to insert:");
scanf("%c", &PreElem);
getchar();
Tmp = Find(L, PreElem); printf("What element do you want to insert:");
scanf("%c", &Ins);
getchar(); Insert(L, Ins, Tmp);
PrintList(L);
//将整个表倒置
Reverse(L);
printf("Now the reverse list is:");
PrintList(L);
//删除整个表
DeleteList(L);
return ;
}

单链表ADT的更多相关文章
- 数据结构:DHUOJ 单链表ADT模板应用算法设计:长整数加法运算(使用单链表存储计算结果)
单链表ADT模板应用算法设计:长整数加法运算(使用单链表存储计算结果) 时间限制: 1S类别: DS:线性表->线性表应用 题目描述: 输入范例: -5345646757684654765867 ...
- [C++]数据结构:线性表之(单)链表
一 (单)链表 ADT + Status InitList(LinkList &L) 初始化(单)链表 + void printList(LinkList L) 遍历(单)链表 + int L ...
- 单链表 C++ 实现 - 含虚拟头节点
本文例程下载链接:ListDemo 链表 vs 数组 链表和数组的最大区别在于链表不支持随机访问,不能像数组那样对任意一个(索引)位置的元素进行访问,而需要从头节点开始,一个一个往后访问直到查找到目标 ...
- 动态单链表的传统存储方式和10种常见操作-C语言实现
顺序线性表的优点:方便存取(随机的),特点是物理位置和逻辑为主都是连续的(相邻).但是也有不足,比如:前面的插入和删除算法,需要移动大量元素,浪费时间,那么链式线性表 (简称链表) 就能解决这个问题. ...
- python数据结构与算法之单链表
表的抽象数据类型 ADT list: #一个表的抽象数据类型 List(self) #表的构造操作,创建一个空表 is_empty ...
- JAVA实现具有迭代器的线性表(单链表)
一,迭代器的基本知识: 1,为什么要用迭代器?(迭代:即对每一个元素进行一次“问候”) 比如说,我们定义了一个ADT(抽象数据类型),作为ADT的一种实现,如单链表.而单链表的基本操作中,大部分需要用 ...
- 单链表-Python实现-jupyter->markdown 格式测试
单链表引入 顺序表 理解Python变量的本质: 变量存储的不是值,是值的地址 理解Python的 "="表示的是指向关系 案例: 交换a,b的值, a=10, b=20 a, b ...
- C++泛化单链表
泛型单链表 单链表将每个数据分为节点,每个节点存储数据和指向下一个节点的指针.这样数据就不用在内存中使用连续的存储空间,有更大的灵活性. 这里将单链表分为节点类(Node)和链表类(singleLin ...
- 时间复杂度分别为 O(n)和 O(1)的删除单链表结点的方法
有一个单链表,提供了头指针和一个结点指针,设计一个函数,在 O(1)时间内删除该结点指针指向的结点. 众所周知,链表无法随机存储,只能从头到尾去遍历整个链表,遇到目标节点之后删除之,这是最常规的思路和 ...
随机推荐
- React.js小书总结
(迁移自旧博客2017 08 27) 第一阶段 react的组件相当于MVC里面的View. react.js 将帮助我们将界面分成了各个独立的小块,每一个块就是组件,这些组件之间可以组合.嵌套,就成 ...
- python数据库多字段插入
# -*- co;ding: utf-8 -*-#企业详细信息写入数据库+征信得分import pymysqlfrom impala.dbapi import connect conn = pymys ...
- linux,vim和bash命令小册
linux命令 命令 功能 cd old 进入old文件夹 ll -a 当前文件列表(包含隐藏文件) rm -rf old 删除old文件夹(包含子文件夹) mkdir old 新建old文件夹 ps ...
- week 10--了解原型设计的工具
了解原型设计的工具 随着原型应用的普及,越来越多的产品会采用原型设计来表述.完善整体需求,这样做自然有其原因.首先原型的制作成本和演示成本都比较低,除非比较复杂或者保真度要求比较高的原型,在描述一个功 ...
- 简单H5单页面真机调试
1.安装Node.js 这个没什么好说的,直接去官网下载安装就好了. Node.js官网:https://nodejs.org 2.安装http-server 直接在命令行中安装到全局(-g表示安装到 ...
- Shopping List
剃须啫喱 吉列 70g $22.00 鲁阳家居专营店 剃须水套装 阿帕奇+酷曼 230g+230g $16.80(限时活动) 鲁阳家居专营店 鸡胸肉 撸铁党 100gx9+100g $49.9(限时活 ...
- F1赛道 - Bahrain International Circuit | 巴林国际赛道
刚看完F1巴林站比赛,23点到1点,整整两个小时,比赛相当精彩. 从排位赛结果看,法拉利似乎肯定包揽1-2名,可惜天公不作美,今晚风大.沙多:vettel自己失误,鼻翼掉了,还在被汉密尔顿超车的时候自 ...
- MIUI8系统完整刷入开发版开启root权限的经验
小米的机器不同手机型号一般情况官网都提供两个不同的安卓系统版本,可分为稳定版和开发版,稳定版没有提供root超级权限管理,开发版中就支持了root超级权限,很多情况我们需要使用的一些功能强大的APP, ...
- Matlab-6:解非线性方程组newton迭代法
函数文件: function x=newton_Iterative_method(f,n,Initial) x0=Initial; tol=1e-11; x1=x0-Jacobian(f,n,x0)\ ...
- tortoisegit里的cleanup坑
tortoisegit的clean up功能(以下红框部分)真的不要去点啊,你所有被ignore(忽略)的本地文件会被全部删除,而且是无法恢复的,因为远程仓库里根本就没有这些文件. 血的教训啊,本以为 ...