单链表和顺序表都是线性表,其外在操作完全一致。唯一的差异就在存储结构上,就是这点差异导致了迥然不同的代码实现。话不多说,赶紧上车吧!
运行效果图:
1.单链表初始化过程

2.遍历单链表

3.为单链表追加元素

4.为单链表删除元素

5.为单链表插入元素

6.为单链表定位元素




。因单链表与顺序表的外在操作完全相同,故省去部分运行效果图


7.清空单链表

至此,运行效果图展示完毕!


附代码

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>#define OK 1
#define ERROR -1
#define SPAN 35;//菜单的水平跨度
#define VerticalGap 1//菜单的垂直间距,1就是一个换行,2就是两个换行
typedef struct node {int data;//数据域struct node *next;//指针域
} *NodePointer, Node;NodePointer initialize();//初始化链表
void manifest(NodePointer originNodePointer);//遍历链表
int sort(NodePointer originNodePointer);//给链表排序
int inverse(NodePointer originNodePointer);//逆转链表中的所有结点的有效数据
void append(NodePointer originNodePointer, int value);//为链表追加结点,也就是在链表末尾添加一个结点
int insert(NodePointer originNodePointer, int position, int value);//在链表指定的位置上插入新结点
int delete(NodePointer originNodePointer, int position);//删除链表中某一结点的值
int modify(NodePointer originNodePointer, int position, int value);//修改表中的某一结点值
int getNode(NodePointer originNodePointer, int position, int *value);//通过结点下标获取结点值,如果成功获取返回1,否则返回-1
int locateNode(NodePointer originNodePointer, int value);//通过结点的值获取结点下标。若结点不存在或链表为空,则返回-1;若结点存在,则返回下标。
void clear(NodePointer originNodePointer);//清空链表
int isEmpty(NodePointer originNodePointer);//判断链表是否为空
void prompt(char *prompt);//运用了字符串和指针的知识,对printf的简单封装
void inputData(int *data, char *dataExplanation);//运用了字符串和指针的知识,对scanf和printf的简单封装
void menu(char **menu, int length);//动态地输出菜单
void duplicate(int size, char token);//给出一个整数size和一个字符型符号token,输出size个token,不换行
int main() {char *operatingMenu[] = {"LinkedList","1.reinitialize list", "2.present list", "3.append element","4.delete element", "5.insert element", "6.modify element","7.get element", "8.locate element", "9.sort", "10.inverse","11.clear list", "12.exit"};int length = sizeof(operatingMenu) / sizeof(char *);int indicator, position, value, status;NodePointer originNodePointer = initialize();while (1) {system("cls");menu(operatingMenu, length);if (originNodePointer == NULL || isEmpty(originNodePointer)) {prompt("The List Is Empty.Data are required!");} else {printf("CURRENT TOTAL:\t%d\n", originNodePointer->data);manifest(originNodePointer);}inputData(&indicator, "type in number:\t");switch (indicator) {case 1:if (isEmpty(originNodePointer)) {free(originNodePointer);//若链表有效数据节点已经释放,则释放起源结点即可} else//否则,先释放链表有效数据节点,再释放起源结点{clear(originNodePointer);free(originNodePointer);//起源结点单独释放}originNodePointer = initialize();//给起源结点指针重新赋值system("pause");break;case 2:manifest(originNodePointer);system("pause");break;case 3:inputData(&value, "VALUE:");append(originNodePointer, value);manifest(originNodePointer);system("pause");break;case 4:inputData(&position, "POSITION:");status = delete(originNodePointer, position);(status == OK) ? manifest(originNodePointer) : prompt("check out and try again!");system("pause");break;case 5:inputData(&position, "POSITION:");inputData(&value, "VALUE:");status = insert(originNodePointer, position, value);(status == OK) ? manifest(originNodePointer) : prompt("check out and try again!");system("pause");break;case 6:inputData(&position, "POSITION:");inputData(&value, "VALUE:");status = modify(originNodePointer, position, value);(status == OK) ? manifest(originNodePointer) : prompt("check out and try again!");system("pause");break;case 7:inputData(&position, "POSITION:");status = getNode(originNodePointer, position, &value);(status == OK) ? printf("VALUE: %d\n", value) : prompt("check out and try again!");system("pause");break;case 8:inputData(&value, "VALUE:");position = locateNode(originNodePointer, value);(position == ERROR) ? prompt("check out and try again!") : printf("POSITION:%d\n", position);system("pause");break;case 9:status = sort(originNodePointer);(status == OK) ? manifest(originNodePointer) : prompt("check out and try again!");system("pause");break;case 10:status = inverse(originNodePointer);(status == OK) ? manifest(originNodePointer) : prompt("check out and try again!");system("pause");break;case 11:clear(originNodePointer);system("pause");break;case 12:if (isEmpty(originNodePointer))//若有效结点均已释放完毕{free(originNodePointer);//释放起源结点} else//否则,先释放链表所有有效节点,再释放起源结点{clear(originNodePointer);free(originNodePointer);}exit(-1);}}
}NodePointer initialize() {int length;inputData(&length, "The length of List:");if (length <= 0)exit(-1);NodePointer originNodePointer = (NodePointer) malloc(sizeof(Node));if (originNodePointer == NULL) {prompt("Failed To Allocate Memory!");exit(-1);}originNodePointer->data = 0;//起源结点的数据域存放有效结点的个数NodePointer newborn = originNodePointer;NodePointer temp;for (int i = 0; i < length; ++i) {temp = (NodePointer) malloc(sizeof(Node));printf("element %d:", i + 1);scanf("%d", &(temp->data));temp->next = NULL;newborn->next = temp;newborn = temp;originNodePointer->data++;//链表中有效结点的个数加1}return originNodePointer;
}void manifest(NodePointer originNodePointer) {if (isEmpty(originNodePointer)) {prompt("The List Is Empty");return;}NodePointer newborn = originNodePointer->next;printf("{");for (; newborn != NULL; newborn = newborn->next) {if (newborn->next != NULL)printf("%d\t", newborn->data);elseprintf("%d", newborn->data);}printf("}\n");
}void append(NodePointer originNodePointer, int value) {NodePointer newborn = originNodePointer;NodePointer renascence = (NodePointer) malloc(sizeof(Node));if (renascence == NULL) {prompt("Failed To Allocate Memory!");exit(-1);}renascence->data = value;renascence->next = NULL;while (newborn->next != NULL) {newborn = newborn->next;}newborn->next = renascence;originNodePointer->data++;//起源结点存放链表有效结点的个数,在插入结点后加1
}int insert(NodePointer originNodePointer, int position, int value) {//要想在链表中插入结点Amanda,先要定位到该结点Amanda上一个结点Natasha的位置//并且判断结点Natasha有没有后继结点,// 若没有,则表明Natasha就是链表表尾,插入的位置无效;//若有,则表明插入的位置合法,可以插入该结点if (isEmpty(originNodePointer)) {prompt("The List Is Empty");return ERROR;}NodePointer newborn = originNodePointer;int i;for (i = 1; i < position && newborn->next != NULL; ++i)//我们从逻辑上将链表当作数组从前往后遍历{newborn = newborn->next;}if (i > position || newborn->next == NULL)//若输入的position小于0,则i>position,那么就判定position非法。再一个判断是否已经到达链表表尾{prompt("INVALID POSITION");return ERROR;}NodePointer renascence = (NodePointer) malloc(sizeof(Node));renascence->next = newborn->next;renascence->data = value;newborn->next = renascence;originNodePointer->data++;//结点数量加1prompt("The element is inserted completely!");return OK;
}int delete(NodePointer originNodePointer, int position) {//删除结点与插入结点相同,同样要定位到要删除结点Amanda的上一个结点Natasha的位置,后面不再赘述if (isEmpty(originNodePointer)) {prompt("The List Is Empty");return ERROR;}NodePointer newborn = originNodePointer;int i;for (i = 1; i < position && newborn->next != NULL; ++i) {newborn = newborn->next;}if (i > position || newborn->next == NULL) {prompt("INVALID POSITION");return ERROR;}NodePointer destroyedNode = newborn->next;newborn->next = destroyedNode->next;free(destroyedNode);originNodePointer->data--;prompt("The element is deleted successfully!");return OK;
}int modify(NodePointer originNodePointer, int position, int value) {if (isEmpty(originNodePointer)) {prompt("The List Is Empty");return ERROR;}if (position <= 0 || position > originNodePointer->data) {prompt("INVALID POSITION");return ERROR;}NodePointer newborn = originNodePointer;for (int i = 1; i <= position; ++i)newborn = newborn->next;newborn->data = value;prompt("The modification is completed!");return OK;
}int getNode(NodePointer originNodePointer, int position, int *value) {if (isEmpty(originNodePointer)) {prompt("The List Is Empty");return ERROR;}if (position <= 0 || position > originNodePointer->data) {prompt("INVALID POSITION");return ERROR;}NodePointer newborn = originNodePointer;for (int i = 1; i <= position; ++i) {newborn = newborn->next;}*value = newborn->data;return OK;
}int locateNode(NodePointer originNodePointer, int value) {if (isEmpty(originNodePointer)) {prompt("The List Is Empty");return ERROR;}NodePointer newborn = originNodePointer;int i = 1;int position;for (; i <= originNodePointer->data; ++i) {newborn = newborn->next;if (newborn->data == value) {position = i;break;}}if (i > originNodePointer->data) {prompt("The element you are looking for doesn't exist!");return ERROR;} elsereturn position;
}void clear(NodePointer originNodePointer)//清空链表时,保留起源起点
{if (originNodePointer->next == NULL) {prompt("There is no need to clear!");return;}NodePointer newborn = originNodePointer;NodePointer temporaryNode;int temp;for (int i = 1; i <= originNodePointer->data; ++i) {temporaryNode = newborn->next;temp = temporaryNode->data;newborn->next = temporaryNode->next;free(temporaryNode);printf("The element {\t%d\t} is released completely!\n", temp);}originNodePointer->data = 0;//起源结点的数据域存放链表有效结点的个数,在链表清空后归零
}int sort(NodePointer originNodePointer)//这里用一个简单的选择排序
{if (isEmpty(originNodePointer)) {prompt("The List Is Empty");return ERROR;}NodePointer competitor = originNodePointer->next;NodePointer opponent = NULL;NodePointer exchange = NULL;int temp;for (; competitor->next != NULL; competitor = competitor->next) {//最外层循环competitor只运算前n-1个元素,第n个元素已经是链表表尾,不参后续运算,循环结束exchange = competitor;for (opponent = competitor->next; opponent != NULL; opponent = opponent->next)//内层循环opponent运算到最后一个元素,最后一个元素指针域的指针为空,退出循环if (exchange->data > opponent->data)exchange = opponent;if (exchange != competitor) {temp = exchange->data;exchange->data = competitor->data;competitor->data = temp;}}prompt("Sorting is completed!");return OK;
}int inverse(NodePointer originNodePointer) {if (isEmpty(originNodePointer)) {prompt("The List Is Empty");return ERROR;}NodePointer begin = originNodePointer->next;NodePointer end = originNodePointer->next;int counter = originNodePointer->data / 2;int temp;int j = 0;for (int i = 0; i < counter; i++, begin = begin->next) //从逻辑将链表有效节点当成数组来操作{while (j < originNodePointer->data - 1 - i)//定位到对应的交换节点位置{++j;end = end->next;}//第一个有效结点和倒数第一个有效结点交互数据域,第二个有效结点和倒数第二个结点交换数据域,依此类推temp = end->data;end->data = begin->data;begin->data = temp;j = 0;end = originNodePointer->next;}prompt("Inverse is completed!");return OK;
}int isEmpty(NodePointer originNodePointer) {if (originNodePointer->next == NULL)return 1;elsereturn 0;
}void inputData(int *data, char *dataExplanation) {printf("%s", dataExplanation);scanf("%d", data);
}void prompt(char *prompt) {printf("%s\n", prompt);
}void menu(char **origin, int length) {int span = SPAN;int gapLength;duplicate(span, '*');duplicate(1, '\n');for (int i = 0; i < length; ++i) {duplicate(1, '*');gapLength = span - (strlen(*(origin + i))) - 2;duplicate(gapLength / 2, ' ');printf("%s", origin[i]);if (gapLength % 2 == 0) {duplicate(gapLength / 2, ' ');} else {duplicate(gapLength / 2 + 1, ' ');}duplicate(1, '*');duplicate(VerticalGap, '\n');}duplicate(span, '*');duplicate(1, '\n');
}void duplicate(int size, char token) {for (int i = 0; i < size; ++i) {printf("%c", token);}
}

线性表的链式存储-单链表,从认识到实践相关推荐

  1. 【数据结构】线性表的链式存储-单链表

    单链表的定义 线性表的链式存储又称为单链表,它是指通过一组任意的存储单元来存储线性表中的数据元素. 为了建立起数据元素之间的线性关系,对每个链表结点,除了存放元素自身的信息之外,还需要存放一个指向其后 ...

  2. 线性表的链式存储-单链表

    单链表操作 [x] 单链表的创建(尾插法.头插法) [x] 单链表的查找操作 [x] 单链表的删除操作 [x] 单链表的逆置操作(使用头插法) [x] 单链表表长的计算 [x] 打印单链表 单链表的创 ...

  3. 线性表的链式表示——单链表

    单链表 定义 线性表的链式存储又称单链表,它是指通过一组任意的存储单元来存储线性表中的数据元素.每个链表的结点,除存放元素自身的信息之外,还需要存放一个指向其后继结点的指针.即单链表的结构分为两部分, ...

  4. 线性表的链式实现(单链表)

    单链表的定义 为了表示每个数据元素与其直接后续元素之间的逻辑关系,每个元素除了存储本身的信息外,还需要存储指示其直接后续的信息,即每个结点存放本身的数据元素和下一个元素的地址.n个结点连接成一个链式线 ...

  5. 用Java描述数据结构之线性表的链式存储(链表),模拟LinkedList实现

    上一篇介绍了顺序表:用Java描述数据结构之线性表的顺序存储(顺序表),ArrayList及其方法的介绍 上一篇博客中说明了什么是线性表--线性表就是一个个数据元素逻辑上以一对一的相邻关系(但是在物理 ...

  6. 【数据结构】线性表的链式存储-双链表

    引言 单链表结点中只有一个指向其后继的指针,这使得单链表只能从头结点依次顺序地向后遍历.若要访问某个结点的前驱结点(插入.删除操作时),只能从头开始遍历 ,访问后继结点的时间复杂度为 0(1),访问前 ...

  7. 数据结构(四) -- C语言版 -- 线性表的链式存储 - 循环链表

    文章目录 零.读前说明 一.循环链表的概述 二.循环链表的模型 2.1.包含头节点模型 2.2.不包含头节点模型 三.工程结构及简单测试案例 3.1.测试工程的目录结构 3.2.循环链表示例源码 3. ...

  8. 什么是线性表?什么是线性表的顺序存储结构?什么是线性表的链式存储结构?

    1.线性表是最简单也是最常用的一种数据结构.线性表的例子不胜枚举,例如,英文字母表就是一个线性表,表中的英文字母是一个数据元素. 2.线性表的定义:线性表是具有相同特性的数据元素的一个有限序列. 3. ...

  9. 《数据结构》c语言版学习笔记——单链表结构(线性表的链式存储结构Part1)

    线性表的链式存储结构 数据结构系列文章 第二章 单链表结构 文章目录 线性表的链式存储结构 前言 一.单链表的建立 代码 二.单链表的读取 代码 三.单链表的插入 代码 四.单链表的删除 代码 五.单 ...

  10. 数据结构第三篇——线性表的链式存储之单链表

    ♥注:未经博主同意,不得转载. 线性表的链式存储结构的特点是用一组任意的存储单元来存储线性表的数据元素,这些单元可以分散在内存中的任意位置上,其在物理上可以是连续的,也可以是不连续的.具有链式存储结构 ...

最新文章

  1. 证书 vivo_iQOO 5 Pro获泰尔实验室首张流畅性能体验五星证书
  2. python 代码-python经典代码
  3. vsc系统是什么意思_电脑蓝屏是什么意思?蓝屏就一定要重装系统吗?你可不要弄错了...
  4. Android Studio百度地图开发所需参数获取SHA1或MD5的最简单方法(图文教程)
  5. [算法]不用第三个数交换2个数的位置
  6. 解决loaded more than 1 DLL from .libs和No metadata found in lib\site-packages两个错误
  7. nginx 的源码安装
  8. [解读REST] 6.REST的应用经验以及教训
  9. CentOS查看CPU,内存,位数行等信息命令
  10. codeblock异常关闭,重新开机,启动时提示有另外的实例在运行的解决办法。
  11. unity数组或链表需要空间很大赋值与调用
  12. Nginx 安装使用
  13. AD 常见绿色报错的消除
  14. 电脑卡住了怎么保存excel_win7系统遇到死机没及时保存excel文件该怎么办
  15. docker之SonarQube导出PDF报告
  16. 支付宝实现JS调起支付你必须知道的坑(40004 ACQ.INVALID_PARAMETER)
  17. ketchup 消息队列rabbitmq使用
  18. 几种常见音频编码器的比较
  19. Appbase基础框架
  20. XILINX DMA/Bridge Subsystem for PCI Express (XDMA)笔记1(基于VU250 board)

热门文章

  1. 【网络工程】2、eNSP工具下载与安装
  2. 工程项目管理——第七章 软件进度管理
  3. 幼儿编程Scratch第31讲:垃圾车-乐高入门机器人-WeDo
  4. 一文解读KANO模型
  5. matlab sil,丰田使用高精度发动机模型和SIL+M前置开发发动机控制系统
  6. mysql 唯一索引 死锁_MySQL死锁案例_唯一索引
  7. 浙大计算机科学与技术专业课表,浙江大学 计算机科学与技术专业课程设置
  8. Yasm入门-hello world
  9. 机械类有哪些好投一些的核心期刊?
  10. 三轴加速度传感器的类型、原理、特点和应用