数据结构C语言实现系列——线性表(线性表链接存储(单链表))
#include <stdio.h>
#include <stdlib.h>
#define NN 12
#define MM 20
typedef int elemType ;
/*******************************************************/
/* 以下是关于线性表链接存储(单链表)操作的16种算法 */
/*******************************************************/
struct sNode{ /* 定义单链表结点类型 */
elemType data;
struct sNode *next;
};
/* 1.初始化线性表,即置单链表的表头指针为空 */
void initList(struct sNode* *hl)
{
*hl = NULL;
return;
}
/* 2.清除线性表L中的所有元素,即释放单链表L中所有的结点,使之成为一个空表 */
void clearList(struct sNode* *hl)
{
/* cp和np分别作为指向两个相邻结点的指针 */
struct sNode *cp, *np;
cp = *hl;
/* 遍历单链表,依次释放每个结点 */
while(cp != NULL){
np = cp->next; /* 保存下一个结点的指针 */
free(cp);
cp = np;
}
*hl = NULL; /* 置单链表的表头指针为空 */
return;
}
/* 3.返回单链表的长度 */
int sizeList(struct sNode *hl)
{
int count = 0; /* 用于统计结点的个数 */
while(hl !
= NULL){
count++;
hl = hl->next;
}
return count;
}
/* 4.检查单链表是否为空,若为空则返回1,否则返回0 */
int emptyList(struct sNode *hl)
{
if(hl == NULL){
return 1;
}else{
return 0;
}
}
/* 5.返回单链表中第pos个结点中的元素,若pos超出范围,则停止程序运行 */
elemType getElem(struct sNode *hl, int pos)
{
int i = 0; /* 统计已遍历的结点个数 */
if(pos < 1){
printf("pos值非法,退出运行! ");
exit(1);
}
while(hl != NULL){
i++;
if(i == pos){
break;
}
hl = hl->next;
}
if(hl != NULL){
return hl->data;
}else{
printf("pos值非法,退出运行! ");
exit(1);
}
}
/* 6.遍历一个单链表 */
void traverseList(struct sNode *hl)
{
while(hl !
= NULL){
printf("%5d", hl->data);
hl = hl->next;
}
printf(" ");
return;
}
/* 7.从单链表中查找具有给定值x的第一个元素,若查找成功则返回该结点data域的存储地址,否则返回NULL */
elemType* findList(struct sNode *hl, elemType x)
{
while(hl != NULL){
if(hl->data == x){
return &hl->data;
}else{
hl = hl->next;
}
}
return NULL;
}
/* 8.把单链表中第pos个结点的值修改为x的值,若修改成功返回1,否则返回0 */
int updatePosList(struct sNode *hl, int pos, elemType x)
{
int i = 0;
struct sNode *p = hl;
while(p != NULL){ /* 查找第pos个结点 */
i++;
if(pos == i){
break;
}else{
p = p->next;
}
}
if(pos == i){
p->data = x;
return 1;
}else{
return 0;
}
}
/* 9.向单链表的表头插入一个元素 */
void insertFirstList(struct sNode* *hl, elemType x)
{
struct sNode *newP;
newP = malloc(sizeof(struct sNode));
if(newP == NULL){
printf("内存分配失败,退出运行!
");
exit(1);
}
newP->data = x; /* 把x的值赋给新结点的data域 */
/* 把新结点作为新的表头结点插入 */
newP->next = *hl;
*hl = newP;
return;
}
/* 10.向单链表的末尾添加一个元素 */
void insertLastList(struct sNode* *hl, elemType x)
{
struct sNode *newP;
newP = malloc(sizeof(struct sNode));
if(newP == NULL){
printf("内在分配失败,退出运行! ");
exit(1);
}
/* 把x的值赋给新结点的data域,把空值赋给新结点的next域 */
newP->data = x;
newP->next = NULL;
/* 若原表为空,则作为表头结点插入 */
if(*hl == NULL){
*hl = newP;
}
/* 查找到表尾结点并完成插入 */
else{
struct sNode *p = NULL;
while(p->next != NULL){
p = p->next;
}
p->next = newP;
}
return;
}
/* 11.向单链表中第pos个结点位置插入元素为x的结点,若插入成功返回1,否则返回0 */
int insetPosList(struct sNode* *hl, int pos, elemType x){
int i = 0;
struct sNode *newP;
struct sNode *cp = *hl, *ap = NULL;
/* 对pos值小于等于0的情况进行处理 */
if(pos <= 0){
printf("pos值非法,返回0表示插入失败!
");
return 0;
}
/* 查找第pos个结点 */
while(cp != NULL){
i++;
if(pos == i){
break;
}else{
ap = cp;
cp = cp->next;
}
}
/* 产生新结点,若分配失败,则停止插入 */
newP = malloc(sizeof(struct sNode));
if(newP == NULL){
printf("内存分配失败,无法进行插入操作! ");
return 0;
}
/* 把x的值赋给新结点的data域 */
newP->data = x;
/* 把新结点插入到表头 */
if(ap == NULL){
newP->next = cp; /* 或改为newP->next = *hl; */
*hl = newP;
}
/* 把新结点插入到ap和cp之间 */
else{
newP->next = cp;
ap->next = newP;
}
return 1; /* 插入成功返回1 */
}
/* 12.向有序单链表中插入元素x结点,使得插入后仍然有序 */
void insertOrderList(struct sNode* *hl, elemType x)
{
/* 把单链表的表头指针赋给cp,把ap置空 */
struct sNode *cp = *hl, *ap = NULL;
/* 建立新结点 */
struct sNode *newP;
newP = malloc(sizeof(struct sNode));
if(newP == NULL){
printf("内在分配失败,退出运行!
");
exit(1);
}
newP->data = x; /* 把x的值赋给新结点的data域 */
/* 把新结点插入到表头 */
if((cp == NULL) (x < cp->data)){
newP->next = cp;
*hl = newP;
return;
}
/* 顺序查找出x结点的插入位置 */
while(cp != NULL){
if(x < cp->data){
break;
}else{
ap = cp;
cp = cp->next;
}
}
/* 把x结点插入到ap和cp之间 */
newP->next = cp;
ap->next = newP;
return;
}
/* 13.从单链表中删除表头结点,并把该结点的值返回,若删除失败则停止程序运行 */
elemType deleteFirstList(struct sNode* *hl)
{
elemType temp;
struct sNode *p = *hl; /* 暂存表头结点指针,以便回收 */
if(*hl == NULL){
printf("单链表为空,无表头可进行删除,退出运行! ");
exit(1);
}
*hl = (*hl)->next; /* 使表头指针指向第二个结点 */
temp = p->data; /* 暂存原表头元素,以便返回 */
free(p); /* 回收被删除的表头结点 */
return temp; /* 返回第一个结点的值 */
}
/* 14.从单链表中删除表尾结点并返回它的值,若删除失败则停止程序运行 */
elemType deleteLastList(struct sNode* *hl)
{
elemType temp;
/* 初始化cp和ap指针,使cp指向表头结点,使ap为空 */
struct sNode *cp = *hl;
struct sNode *ap = NULL;
/* 单链表为空则停止运行 */
if(cp == NULL){
printf("单链表为空,无表头进行删除,退出运行!
");
exit(1);
}
/* 从单链表中查找表尾结点,循环结束时cp指向表尾结点,ap指向其前驱结点 */
while(cp->next != NULL){
ap = cp;
cp = cp->next;
}
/* 若单链表中只有一个结点,则需要修改表头指针 */
if(ap == NULL){
*hl = (*hl)->next; /* 或改为*hl = NULL; */
}
/* 删除表尾结点 */
else{
ap->next = NULL;
}
/* 暂存表尾元素,以便返回 */
temp = cp->data;
free(cp); /* 回收被删除的表尾结点 */
return temp; /* 返回表尾结点的值 */
}
/* 15.从单链表中删除第pos个结点并返回它的值,若删除失败则停止程序运行 */
elemType deletePosList(struct sNode* *hl, int pos)
{
int i = 0;
elemType temp;
/* 初始化cp和ap指针,使cp指向表头结点,使ap为空 */
struct sNode *cp = *hl;
struct sNode *ap = NULL;
/* 单链表为空或pos值非法则停止运行 */
if((cp == NULL) (pos <= 0)){
printf("单链表为空或pos值不正确,退出运行!
");
exit(1);
}
/* 从单链表中查找第pos个结点,找到后由cp指向该结点,由ap指向其前驱结点 */
while(cp != NULL){
i++;
if(i == pos){
break;
}
ap = cp;
cp = cp->next;
}
/* 单链表中没有第pos个结点 */
if(cp == NULL){
printf("pos值不正确,退出运行! ");
exit(1);
}
/* 若pos等于1,则需要删除表头结点 */
if(pos == 1){
*hl = (*hl)->next; /* 或改为*hl = cp->next; */
}
/* 否则删除非表头结点,此时cp指向该结点,ap指向前驱结点 */
else{
ap->next = cp->next;
}
/* 暂存第pos个结点的值,以便返回 */
temp = cp->data;
free(cp); /* 回收被删除的第pos个结点 */
return temp; /* 返回在temp中暂存的第pos个结点的值 */
}
/* 16.从单链表中删除值为x的第一个结点,若删除成功则返回1,否则返回0 */
int deleteValueList(struct sNode* *hl, elemType x)
{
/* 初始化cp和ap指针,使cp指向表头结点,使ap为空 */
struct sNode *cp = *hl;
struct sNode *ap = NULL;
/* 从单链表中查找值为x的结点,找到后由cp指向该结点,由ap指向其前驱结点 */
while(cp !
= NULL){
if(cp->data == x){
break;
}
ap = cp;
cp = cp->next;
}
/* 若查找失败,即该单链表中不存在值为x的结点,则返回0 */
if(cp == NULL){
return 0;
}
/* 如果删除的是表头或非表头结点则分别进行处理 */
if(ap == NULL){
*hl = (*hl)->next; /* 或改为*hl= cp->next */
}else{
ap->next = cp->next;
}
free(cp); /* 回收被删除的结点 */
return 1; /* 返回1表示删除成功 */
}
/************************************************************************/
int main(int argc, char* argv[])
{
int a[NN];
int i;
struct sNode *p, *h, *s;
srand(time(NULL));
initList(&p);
for(i = 0; i < NN; i++){
a[i] = rand() & MM;
}
printf("随机数序列:");
for(i = 0; i < NN; i++){
printf("%5d", a[i]);
}
printf(" ");
printf("随机数逆序:");
for(i = 0; i < NN; i++){
insertFirstList(&p, a[i]);
}
traverseList(p);
printf("单链表长度:%5d ", sizeList(p));
for(h = p; h != NULL; h = h->next){
while(deleteValueList(&(h->next), h->data)){
;
}
}
printf("去除重复数:");
traverseList(p);
printf("单链表长度:%5d ", sizeList(p));
h = NULL;
for(s = p; s != NULL; s = s->next){
insertOrderList(&h, s->data);
}
printf("有序表序列:");
traverseList(h);
clearList(&p);
system("pause");
return 0;
}
数据结构C语言实现系列——线性表(线性表链接存储(单链表))的更多相关文章
- 【数据结构(C语言版)系列一】 线性表
最近开始看数据结构,该系列笔记简单记录总结下所学的知识,更详细的推荐博主StrayedKing的数据结构系列,笔记部分也摘抄了博主总结的比较好的内容. 一些基本概念和术语 数据是对客观事物的符号表示, ...
- javascript实现数据结构:线性表--线性链表(链式存储结构)
上一节中, 线性表的顺序存储结构的特点是逻辑关系上相邻的两个元素在物理位置上也相邻,因此可以随机存取表中任一元素,它的存储位置可用一个简单,直观的公式来表示.然后,另一方面来看,这个特点也造成这种存储 ...
- C 线性表的链式存储实现及插入、删除等操作示例
一.链式存储的优势 线性表的存储可以通过顺序存储或链式存储实现,其中顺序存储基于数组实现(见本人上一篇博客),在进行插入删除等操作时,需对表内某一部分元素逐个移动,效率较低.而链式结构不依赖于地址连续 ...
- C++线性表的链式存储结构
C++实现线性表的链式存储结构: 为了解决顺序存储不足:用线性表另外一种结构-链式存储.在顺序存储结构(数组描述)中,元素的地址是由数学公式决定的,而在链式储存结构中,元素的地址是随机分布的,每个元素 ...
- 数据结构C语言实现系列——线性表(单向链表)
#include <stdio.h> #include <stdlib.h> #define NN 12 #define MM 20 typedef int elemType ...
- 数据结构-线性表的链式存储相关算法(C语言实现)
链表的简单介绍 为什么需要线性链表 当然是为了克服顺序表的缺点,在顺序表中,做插入和删除操作时,需要大量的移动元素,导致效率下降. 线性链表的分类 按照链接方式: 按照实现角度: 线性链表的创建和简单 ...
- 线性表的链式存储——C语言实现
SeqList.h #ifndef _WBM_LIST_H_ #define _WBM_LIST_H_ typedef void List; typedef void ListNode; //创建并且 ...
- 【数据结构(C语言版)系列二】 栈
栈和队列是两种重要的线性结构.从数据结构角度看,栈和队列也是线性表,但它们是操作受限的线性表,因此,可称为限定性的数据结构.但从数据类型角度看,它们是和线性表大不相同的两类重要的抽象数据类型. 栈的定 ...
- 数据结构C语言版--动态顺序表的基本功能实现(二)
/* * 若各个方法结构体变量参数为: &L(即地址符加变量)则结构体变量访问结构成员变量时使用"." * 若为:*L(即取地址符加变量)则结构体变量访问结构体成员变量使用 ...
随机推荐
- Unity3D之协程(Coroutines & Yield )
在Unity中StartCoroutine/yield return这个模式到底是怎么应用的? 比如你要一个方法进行一个比较耗时的复杂运算~同时又想让脚本流畅的进行其他操作而不是卡在那里等该方法执行完 ...
- 前端工程师的PS默认工作区
右侧依次是信息.图层.历史记录,如下图:
- 《BI那点儿事》数据流转换——逆透视转换
逆透视转换将来自单个记录中多个列的值扩展为单个列中具有同样值的多个记录,使得非规范的数据集成为较规范的版本.例如,每个客户在列出客户名的数据集中各占一行,在该行的各列中显示购买的产品和数量.逆透视转换 ...
- LTE Module User Documentation(翻译15)——示例程序、参考场景以及故障检测和调试技巧
LTE用户文档 (如有不当的地方,欢迎指正!) 21 Examples Programs(示例程序) 路径 src/lte/examples/ 包含一些示例仿真程序,这些例子表明如何仿真不 ...
- Shell终端配置
Shell终端配置 How to: Change / Setup bash custom prompt (PS1) 参考链接:https://www.cyberciti.biz/tips/howto- ...
- cocos2d-x lua绑定解析
花了几天时间看了下cocos2d-x lua绑定那块,总算是基本搞明白了,下面分三部分解析lua绑定: 一.lua绑定主要用到的底层函数 lua绑定其本质就是有一个公用的lua_Stack来进行C和L ...
- Linux 下 git连接github的使用
1.安装git sudo apt-get install git 2.创建github帐号 3.Linux创建SSH密钥: ssh-keygen //一直默认 4.将公钥加入到Github账户信息A ...
- Aptana Studio 2启动时提示 Workspace Cannot Be Created 解决办法
今天在安装Aptana Studio 2时出现这个东东,卸载后再安装依旧不行最后找到原因 原因 : 就是由于你把“我的文档”的位置修改造成的. 但Aptana还以为 “我的文档”的位置 是在系统的默认 ...
- jsp页面使用el 按key获取map中的对应值
jsp页面使用el 按key获取map中的对应值 转自:<jsp页面使用el 按key获取map中的对应值>地址:http://blog.csdn.net/baple/article/de ...
- Intellij快捷键