C语言实现数据机构链表的基本操作(从键盘输入生成链表、读取数组生成链表)
利用头插法实现逆置
下面简单介绍一下,算法思想结合图示看
算法思想:“删除”头结点与链表其他结点的原有联系(即将头结点的指针置空),再逐个插入逆置链表的表头(即“头插”到逆置链表中),使它成为逆置链表的“新”的头结点,如此循环,直至原链表为空。
这是鬼话,看不懂可以不看,看下面就行......
void NiList(LinkList &L) //逆置
{
LinkList p = L->next, q; //L->next是头结点的指针,p指针指向了首结点
L->next = NULL; //将头结点的指针置空
while (p != NULL)
{
q = p; //指针q从指向第一个结点开始后移
p = p->next; //指针p从指向第二个结点开始后移
q->next = L->next; //指针q所指向结点的指针q->next指向其上一个结点
L->next = q; //头结点的指针后移
}
}
接下来,进行图解:
刚开始是这样
L->next是头结点指针。循环前的操作,p指向首结点(即第一个结点),头结点的指针置空
进入循环,q和p分别指向第一个和第二个节点
q所指向结点的指针q->next指向其(q->next)上一个结点,这里上一个结点的指针为空,故q->next也为空
L->next = q; //头指针后移,指向首结点
进入第二轮循环,这是发生重大变化的关键时期
q和p继续后移,这个图有点错误懒得改了,就是后移后,指针q指向了b结点,指针p指向了c结点
q所指向结点的指针q->next指向其上一个结点
头指针后移,指向第二个结点
你可以看到此时已经开始逆置,如此循环, 直到p==NULL为空
链表完整代码:
1):从键盘输入生成链表
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h> #define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define TRUE 1
#define FALSE 0 typedef int Status;
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode* next;
}LNode,*LinkList;
/*定义了两种新的数据类型LNode和LinkList,显然各个结点是LNode类型的,
头指针和结点的next成员是LinkList类型的,L是LinkList这个新的结构体指针类型定义的头指针*/ Status InitList(LinkList &L) //初始化
{
L = (LinkList)malloc(sizeof(LNode));
if (L == NULL)return ERROR;
L->next = NULL;
return OK;
} Status ListEmpty(LinkList L) //判空
{
if (L->next == NULL) return TRUE;
return FALSE;
} Status ListInsert(LinkList &L, int i, ElemType e) //插入
{
int j = 0;
LinkList p = L, s; //指针p指向头指针
if (i<1) return ERROR;
while ((p != NULL) && (j<i - 1))
{
p = p->next;
j++;
}
if(p==NULL)return ERROR;
s = (LNode*)malloc(sizeof(LNode)); //生成新节点
if (s == NULL) return ERROR;
s->data = e; //s结点暂存e
s->next = p->next; //s结点的指针s->next指向第i个结点
p->next = s; //第i-1个结点的指针p->next指向s结点
return OK;
} Status ScanfList(LinkList &L) //键盘输入
{
ElemType e;
int i = 1;
printf("输入整数,以0结束:\n");
scanf("%d", &e);
while (e != 0)
{
if (!ListInsert(L, i, e)) return ERROR;
i++;
scanf("%d", &e);
}
return OK;
} Status ListDelete(LinkList &L, int i, ElemType &e) //删除
{
int j = 0;
LinkList p = L, q;
if ((i<1) || (L->next == NULL)) return ERROR;
while ((p != NULL) && (j<i - 1))
{
p = p->next;
j++;
}
if (p == NULL) return ERROR;
q = p->next; //指针q暂存被删结点(第i个结点)的地址
p->next = q->next; //指针p(即第i-1个结点的指针)指向被删结点(第i+1个结点)
e = q->data;
free(q);
return OK;
} Status GetElem(LinkList L, int i, ElemType &e) //取值
{
int j = 1;
LinkList p = L->next;
if (i<1) return ERROR;
while ((p != NULL) && (j<i))
{
p = p->next;
j++;
}
if (p == NULL) return ERROR;
e = p->data;
return OK;
} int LocateElem(LinkList L, ElemType e) //定位
{
int j = 1;
LinkList p = L->next;
while (p != NULL)
{
if (p->data == e)return j;
p = p->next;
j++;
}
return j;
} Status PriorElem(LinkList L, ElemType e, ElemType &pr_e) //直接前驱
{
LinkList p = L->next;
if (p->data == e) return ERROR; //首结点没有直接前驱
while (p != NULL)
{
if (p->next->data == e) break;
p = p->next;
}
if (p == NULL) return ERROR; //指针p一直移到尾结点仍找不到e,返回错误
pr_e = p->data;
return OK;
} int GetLength(LinkList L) //求长度
{
int i = 0;
LinkList p = L;
while (p->next != NULL)
{
p = p->next;
i++;
}
return i;
} void PrnList(LinkList L) //遍历
{
LinkList p = L->next;
while (p != NULL)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
} void NiList(LinkList &L) //逆置
{
LinkList p = L->next, q; //p指针指向了首结点
L->next = NULL; //将头结点的指针置空
while (p != NULL)
{
q = p; //指针q从指向第一个结点开始后移
p = p->next; //指针p从指向第二个结点开始后移
q->next = L->next; //指针q所指向结点的指针q->next指向其上一个结点
L->next = q; //头结点的指针后移
}
} Status Destroy(LinkList &L) //销毁,从首结点开始
{
LinkList p = L->next, q;
while (p != NULL)
{
q = p->next;
free(p);
p = q;
}
free(L);
return OK;
} int main()
{
int i;
ElemType e, e1; LinkList L;
if (InitList(L)) printf("OK\n");
ScanfList(L);
PrnList(L); int k;
printf("\n1.插入\n2:删除\n3:取值\n4:定位\n5:直接前驱\n");
printf("6.求长度\n7:遍历\n8:逆置\n9:销毁\n\n0.退出\n");
scanf("%d", &k);
while (k != 0)
{
switch (k)
{
case 1:
printf("在第几个位置插入何数:");
scanf("%d%d", &i, &e);
if (ListInsert(L, i, e)) printf("OK\n");
break;
case 2:
printf("删除第几个数:");
scanf("%d", &i);
if (ListDelete(L, i, e))printf("删除数为:%d\n", e);
break;
case 3:
printf("获取第几个数:");
scanf("%d", &i);
if (GetElem(L, i, e)) printf("数为:%d\n", e);
break;
case 4:
printf("定位何数:");
scanf("%d", &e);
if (LocateElem(L, e)) printf("位序为:%d\n", LocateElem(L, e));
break;
case 5:
printf("寻找何数直接前驱:");
scanf("%d", &e);
if (PriorElem(L, e, e1)) printf("前驱为:%d\n", e1);
break;
case 6:
printf("表长为:");
printf("%d\n", GetLength(L));
break;
case 7:
printf("遍历:\n");
PrnList(L);
break;
case 8:
NiList(L);
PrnList(L);
printf("逆置成功\n");
break;
case 9:
if (Destroy(L))printf("销毁成功\n");
break;
default:
printf("ERROR\n");
}
scanf("%d", &k);
}
return 0;
}
2):读取数组生成链表
#include<stdio.h>
#include<stdlib.h> #define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define TRUE 1
#define FALSE 0 typedef int Status;
typedef int ElemType;
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
/*定义了两种新的数据类型LNode和LinkList,显然各个结点是LNode类型的,
头指针和结点的next成员是LinkList类型的,L是LinkList结点指针类型定义的头指针*/ Status InitList(LinkList &L) //初始化
{
L = (LinkList)malloc(sizeof(LNode));
if (L == NULL)return ERROR;
L->next = NULL;
return OK;
} Status ListEmpty(LinkList L) //判空
{
if (L->next == NULL)return ERROR;
else return FALSE;
} Status ListInsert(LinkList &L, int i, ElemType e) //插入
{
int j = 0;
LinkList p = L, s; //指针p指向头指针
if (i < 1)return ERROR;
while (p != NULL && j < i - 1)
{
p = p->next;
j++;
}
if (p == NULL)return ERROR;
s = (LNode*)malloc(sizeof(LNode)); //生成新节点
if (s == NULL)return ERROR;
s->data = e; //结点s暂存e
s->next = p->next; //s结点的指针s->next指向第i个结点
p->next = s; //指针p指向s结点
return OK;
} Status CreateList(LinkList &L,ElemType element[], int n) //数组生成链表
{
int i;
for (i = 0; i < n; i++)
if (!ListInsert(L, i + 1, element[i])) return ERROR;
return OK;
} Status ListDelete(LinkList &L, int i, ElemType &e) //删除
{
int j = 0;
LinkList p = L, q;
if (i < 1 || p->next == NULL)return ERROR;
while (p != NULL && j<i - 1)
{
p = p->next;
j++;
}
if (p == NULL)return ERROR;
q = p->next; //指针q暂存被删结点(第i个结点)的地址,故指针q指向了被删结点
p->next = q->next; //指针p(即第i-1个结点的指针)指向被删结点的下一结点(第i+1个结点)
e = q->data;
free(q);
return OK;
} Status GetElem(LinkList L, int i, ElemType &e) //取值
{
int j = 1;
LinkList p = L->next;
if (i < 1)return ERROR;
while (p != NULL && j<i)
{
p = p->next;
j++;
}
if (p == NULL)return ERROR;
e = p->data;
return OK;
} int LocateElem(LinkList L, ElemType e) //定位
{
int j = 1;
LinkList p = L->next;
while (p != NULL)
{
if (p->data == e)return j;
p = p->next;
j++;
}
return j;
} Status PriorElem(LinkList L, ElemType e, ElemType &pr_e) //直接前驱
{
LinkList p = L->next;
if (p->data==e)return ERROR; //首结点没有直接前驱
while (p != NULL)
{
p = p->next;
if (p->next->data == e)break;
}
if (p == NULL)return ERROR; //指针p一直移到尾结点仍找不到e,返回错误
pr_e = p->data;
return OK;
} int GetLength(LinkList L) //求长度
{
int i = 0;
LinkList p = L;
while (p->next != NULL)
{
p = p->next;
i++;
}
return i;
} void PrnList(LinkList L) //遍历
{
LinkList p = L->next;
while (p != NULL)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
} Status NiList(LinkList &L) //逆置
{
LinkList p = L->next, q; //指针p指向了首结点
L->next = NULL; //将头结点指针置空
while (p != NULL)
{
q = p; //指针q从指向第一个结点开始后移
p = p->next; //指针p从指向第二个结点开始后移
q->next = L->next; //指针q所指向结点的指针q->next指向其上一个结点
L->next = q; //头结点的指针后移
}
return OK;
} Status Destroy(LinkList &L) //销毁,从首结点开始
{
LinkList p = L->next, q;
if (p == NULL)return ERROR;
while (p != NULL)
{
q = p->next;
free(p);
p = q;
}
free(L);
return OK;
} int main()
{
int i;
ElemType e, e1; LinkList L;
ElemType element[] = { 15, 3, 59, 27, 8, 11, 32 };
if (InitList(L)) printf("OK\n");
CreateList(L,element,7);
PrnList(L); int k;
printf("\n1.插入\n2:删除\n3:取值\n4:定位\n5:直接前驱\n");
printf("6.求长度\n7:遍历\n8:逆置\n9:销毁\n\n0.退出\n");
scanf("%d", &k);
while (k != 0)
{
switch (k)
{
case 1:
printf("在第几个位置插入何数:");
scanf("%d%d", &i, &e);
if (ListInsert(L, i, e)) printf("OK\n");
break;
case 2:
printf("删除第几个数:");
scanf("%d", &i);
if (ListDelete(L, i, e))printf("删除数为:%d\n", e);
break;
case 3:
printf("获取第几个数:");
scanf("%d", &i);
if (GetElem(L, i, e)) printf("数为:%d\n", e);
break;
case 4:
printf("定位何数:");
scanf("%d", &e);
if (LocateElem(L, e)) printf("位序为:%d\n", LocateElem(L, e));
break;
case 5:
printf("寻找何数直接前驱:");
scanf("%d", &e);
if (PriorElem(L, e, e1)) printf("前驱为:%d\n", e1);
break;
case 6:
printf("表长为:");
printf("%d\n", GetLength(L));
break;
case 7:
printf("遍历:\n");
PrnList(L);
break;
case 8:
NiList(L);
PrnList(L);
printf("逆置成功\n");
break;
case 9:
if (Destroy(L))printf("销毁成功\n");
break;
default:
printf("ERROR\n");
}
scanf("%d", &k);
}
return 0;
}
C语言实现数据机构链表的基本操作(从键盘输入生成链表、读取数组生成链表)的更多相关文章
- C语言 投票系统:给定候选人,从键盘输入候选人的名字,统计票数,并输出最终获胜者
投票系统:给定候选人名单,从键盘输入候选人的名字,统计票数,并输出最终获胜者.若投票人输入的名字不在其候选名单上,则该票数无效. //凯鲁嘎吉 - 博客园 http://www.cnblogs.com ...
- 3012C语言_数据
第二章 数据 2.1 数据类型 2.1.1 数据类型决定 1. 数据占内存字节数 2. 数据取值范围 3. 其上可进行的操作 2.2基本数据类型 2.2.1分类 基本类型 类型 符号 关键字 字节 1 ...
- 数据结构算法C语言实现(五)---2.3重新定义线性链表及其基本操作
一.简述 ...由于链表在空间的合理利用上和插入.删除时不需要移动等的优点,因此在很多场合下,它是线性表的首选存储结构.然而,它也存在着实现某些基本操作,如求线性表的长度时不如顺序存储结构的缺点:另一 ...
- C语言链表的基本操作
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- C++学习笔记48:链表的基本操作
//链表的基本操作 //生成链表,插入结点,查找结点,删除结点,遍历链表,清空链表 //链表类模板 //LinkedList.h #ifndef LINKEDLIST_H #define LINKED ...
- PHP单链表的基本操作
链表的实现 数据结构第一个就是链表了,链表分为两种有直接的数组形式的顺序链,这里不讨论,什么array_push(),array_pop(),函数基本能满足日常的需求,但报告老板,我就是想装个X 上代 ...
- R语言进行数据预处理wranging
R语言进行数据预处理wranging li_volleyball 2016年3月22日 data wrangling with R packages:tidyr dplyr Ground rules ...
- 用Java实现单链表的基本操作
笔试题中经常遇到单链表的考题,下面用java总结一下单链表的基本操作,包括添加删除节点,以及链表转置. package mars; //单链表添加,删除节点 public class ListNode ...
- SQL语言学习-数据定义语言
Sql语言至今已经有6个版本.SQL查询语言包括了所有对数据的操作命令,这些操作可分为四类:数据定义语言(DDL).数据操纵语言(DML).数据控制语言(DCL)和嵌入式SQL语言. 数据定义语言(D ...
随机推荐
- 第6篇scrum冲刺(5.26)
一.站立会议 1.照片 2.工作安排 成员 昨天已完成的工作 今天的工作安排 困难 陈芝敏 研究云开发,更新了登录模块,把用户的信息传入数据库了 学习云开发,云函数调用以及数据的前后端传递 遇 ...
- WS以及NW小世界网络的生成(MATLAB)
WS小世界网络生成算法,一般小世界网络生成算法速度慢,节点度分布与数学推导不符,在网络仿真中造成不便,这里针对实际网络动力学仿真过程撰写了WS小世界网络的MATLAB生成算法,并考虑了矩阵化,具有较高 ...
- SpringCloud系列之Nacos应用篇
前言 原先项目是以SpringConfig作为项目配置中心组件,Eureka作为服务注册发现组件,基本上就是SpringCloud全家桶,Eureka已经停更,所以前期调研可替换方案,主流替换方案有C ...
- oracle之回顾二
TCL 1. 事务(Transaction) 事务(Transaction)是一个操作序列.这些操作要么都做, 要么都不做, 是一个不可分割的工作单元, 是数据库环境中的最小工作单元. 1.1 事务 ...
- Python爬虫 使用selenium处理动态网页
对于静态网页,使用requests等库可以很方便的得到它的网页源码,然后提取出想要的信息.但是对于动态网页,情况就要复杂很多,这种页面的源码往往只有一个框架,其内容都是由JavaScript渲染出来的 ...
- VS2015+opencv3.1.0 imshow()函数出现中文乱码----问题一
Visual Studio提供高级保存选项功能,它能指定特定代码文件的编码规范和行尾所使用的换行符.在Visual Studio 2015中,该命令没有默认显示在“文件”菜单中.用户需要手工设置,才能 ...
- php 循环里面套sql怎么解决
功能要求: 企业列表(展示企业的基本信息,这里只获取了名称.logo.和服务类型), 服务类型说明: 服务类型一共3级,1.2级是必填的,3级是非必填,如果填的话最多3个, 服务类型1.2.3保存在一 ...
- C# OWC11
public void OcwChart(int[] Data,string[] DataName,string Yname,string Xname,string ChartName,string ...
- 【python】我OUT了,原来函数中的冒号和箭头是这么回事
翻了翻httprunner的源代码,越看越不对劲,感觉有点看不懂语法了. 这都什么鬼?感觉心好慌,顿时感到惭愧万分,还好意思说自己了解Python呢. 赶紧了解一下,原来这叫 type hints,是 ...
- springboot配置ssl访问
第一步:########################################### # 端口设置 ########################################### s ...