数据结构链表的初始化插入删除_算法设计:数据结构-线性表

(一)线性表的概念

线性表是具有相同特性元素的有限序列。该序列中所含元素的个数叫做线性表的长度,用n表示(n>=0),注意,n可以等于0表示是一个空表

注意:不同的线性表的数据元素可以不同,但对于同一线性表,各数据元素必须具有相同的数据类型,即同一线性表中各数据元素具有相同的类型,每个数据元素的长度形同

线性表数据结构具有以下特征:

1、有且只有一个首元素

2、有且只有一个尾元素

3、除尾元素之外,其余元素均有唯一的后继元素

4、除首元素之外,其余元素具有唯一的前驱元素

线性表的存储方式有2种:顺序存储和链式存储

(二)顺序表

顺序表是一组地址连续的存储单元一次保存线性表中的数据

要访问第i的元素的位置,可以使用公式求出位置L:

L = ( i – 1 ) * 数据元素长度

例如:数据元素长度为8字节,第3个元素的存储位置为:L = ( 3 – 1 )*8 = 16,即保存第3个元素的地址相对于线性表的首位置偏移16个字节,从这里开始保存第3个数据元素

98bc1e1ed2fd58fbb0bb26ce40763f2c.png

顺序表的详细操作C语言实现如下:

1、循序表操作的头文件

#include

#include

#define MAXSIZE 100 //定义线性表的最大长度

typedef struct //定义顺序表结构

{

DATA ListData[MAXSIZE+1]; //保存顺序表的数组

int ListLen; //顺序表已存结点 的数量

}SeqListType;

void SeqListInit(SeqListType *SL); //初始化顺序表

int SeqListLength(SeqListType *SL); //返回顺序表的元素数量

int SeqListAdd(SeqListType *SL,DATA data); //向顺序表中添加元素

int SeqListInsert(SeqListType *SL,int n,DATA data); //向顺序表中插入元素

int SeqListDelete(SeqListType *SL,int n); //删除顺序表中的据元素

DATA *SeqListFindByNum(SeqListType *SL,int n); //根据序号返回元素

int SeqListFindByCont(SeqListType *SL,char *key); //按关键字查找

int SeqListAll(SeqListType *SL);//遍历顺序表中的内容

2、顺序表的操作

void SeqListInit(SeqListType *SL) //初始化顺序表

{

SL->ListLen=0; //初始化时,设置顺序表长度为0

}

int SeqListLength(SeqListType *SL) //返回顺序表的元素数量

{

return (SL->ListLen);

}

int SeqListAdd(SeqListType *SL,DATA data) //增加元素到顺序表尾部

{

if(SL->ListLen>=MAXSIZE) //顺序表已满

{

printf("顺序表已满,不能再添加结点了!");

return 0;

}

SL->ListData[++SL->ListLen]=data;

return 1;

}

int SeqListInsert(SeqListType *SL,int n,DATA data)

{

int i;

if(SL->ListLen>=MAXSIZE) //顺序表结点数量已超过最大数量

{

printf("顺序表已满,不能插入结点!");

return 0; //返回0表示插入不成功

}

if(n<1 || n>SL->ListLen-1) //插入结点序号不正确

{

printf("插入元素序号错误,不能插入元素!");

return 0; //返回0,表示插入不成功

}

for(i=SL->ListLen;i>=n;i--) //将顺序表中的数据向后移动

SL->ListData[i+1]=SL->ListData[i];

SL->ListData[n]=data; //插入结点

SL->ListLen++; //顺序表结点数量增加1

return 1; //返回成功插入

}

int SeqListDelete(SeqListType *SL,int n) //删除顺序表中的数据元素

{

int i;

if(n<1 || n>SL->ListLen+1) //删除元素序号不正确

{

printf("删除结点序号错误,不能删除结点!");

return 0; //返回0,表示删除不成功

}

for(i=n;iListLen;i++) //将顺序表中的数据向前移动

SL->ListData[i]=SL->ListData[i+1];

SL->ListLen--; //顺序表元素数量减1

return 1; //返回成功删除

}

DATA *SeqListFindByNum(SeqListType *SL,int n) //根据序号返回数据元素

{

if(n<1 || n>SL->ListLen+1) //元素序号不正确

{

printf("结点序号错误,不能返回结点!");

return NULL; //返回0,表示不成功

}

return &(SL->ListData[n]);

}

int SeqListFindByCont(SeqListType *SL,char *key) //按关键字查询结点

{

int i;

for(i=1;i<=SL->ListLen;i++)

if(strcmp(SL->ListData[i].key,key)==0) //如果找到所需结点

return i; //返回结点序号

return 0; //遍历后仍没有找到,则返回0

}

3、测试顺序表

#include

typedef struct

{

char key[15]; //结点的关键字

char name[20];

int age;

} DATA; //定义结点类型,可定义为简单类型,也可定义为结构

#include "2-1 SeqList.h"

#include "2-2 SeqList.c"

int SeqListAll(SeqListType *SL) //遍历顺序表中的结点

{

int i;

for(i=1;i<=SL->ListLen;i++)

printf("(%s,%s,%d)",SL->ListData[i].key,SL->ListData[i].name,SL->ListData[i].age);

}

int main()

{

int i;

SeqListType SL; //定义顺序表变量

DATA data,*data1; //定义结点保存数据类型变量和指针变量

char key[15]; //保存关键字

SeqListInit(&SL); //初始化顺序表

do { //循环添加结点数据

printf("输入添加的结点(学号 姓名 年龄):");

fflush(stdin); //清空输入缓冲区

scanf("%s%s%d",&data.key,&data.name,&data.age);

if(data.age) //若年龄不为0

{

if(!SeqListAdd(&SL,data)) //若添加结点失败

break; //退出死循环

}else //若年龄为0

break; //退出死循环

}while(1);

printf("顺序表中的结点顺序为:");

SeqListAll(&SL); //显示所有结点数据

fflush(stdin); //清空输入缓冲区

printf("要取出结点的序号:");

scanf("%d",&i); //输入结点序号

data1=SeqListFindByNum(&SL,i); //按序号查找结点

if(data1) //若返回的结点指针不为NULL

printf("第%d个结点为:(%s,%s,%d)",i,data1->key,data1->name,data1->age);

fflush(stdin); //清空输入缓冲区

printf("要查找结点的关键字:");

scanf("%s",key); //输入关键字

i=SeqListFindByCont(&SL,key); //按关键字查找 ,返回结点序号

data1=SeqListFindByNum(&SL,i); //按序号查询,返回结点指针

if(data1) //若结点指针不为NULL

printf("第%d个结点为:(%s,%s,%d)",i,data1->key,data1->name,data1->age);

getch();

return 0;

}

(三)链表

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域

使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表

0549f23ae9df715cac76ecd66928bb11.png

链表的详细操作C语言实现如下:

1、链表的定义

#include

typedef struct Node

{

DATA data;

struct Node *next;

}ChainListType;

ChainListType *ChainListAddEnd(ChainListType *head,DATA data); //添加结点到链表末尾

ChainListType *ChainListAddFirst(ChainListType *head,DATA data); //添加结点到链表首部

ChainListType *ChainListFind(ChainListType *head,char *key); //按关键字在链表中查找内容

ChainListType *ChainListInsert(ChainListType *head,char *findkey,DATA data); //插入结点到链表指定位置

int ChainListDelete(ChainListType *head,char *key);//删除指定关键字的结点

int ChainListLength(ChainListType *head);//获取链表结点数量

2、链表的操作

#include

ChainListType *ChainListAddEnd(ChainListType *head,DATA data) //添加结点到链表结尾

{

ChainListType *node,*h;

if(!(node=(ChainListType *)malloc(sizeof(ChainListType))))

{

printf("为保存结点数据申请内存失败!");

return NULL; //分配内存失败

}

node->data=data; //保存数据

node->next=NULL; //设置结点指针为空,即为表尾

if(head==NULL) //头指针

{

head=node;

return head;

}

h=head;

while(h->next!=NULL) //查找链表的末尾

h=h->next ;

h->next=node;

return head;

}

ChainListType *ChainListAddFirst(ChainListType *head,DATA data)

{

ChainListType *node,*h;

if(!(node=(ChainListType *)malloc(sizeof(ChainListType))))

{

printf("为保存结点数据申请内存失败!");

return NULL; //分配内存失败

}

node->data=data; //保存数据

node->next=head; //指向头指针所指结点

head=node; //头指针指向新增结点

return head;

}

ChainListType *ChainListInsert(ChainListType *head,char *findkey,DATA data) //插入结点到链表指定位置

{

ChainListType *node,*node1;

if(!(node=(ChainListType *)malloc(sizeof(ChainListType)))) //分配保存结点的内容

{

printf("为保存结点数据申请内存失败!");

return 0; //分配内存失败

}

node->data=data; //保存结点中的数据

node1=ChainListFind(head,findkey);

if(node1) //若找到要插入的结点

{

node->next=node1->next; //新插入结点指向关键结点的下一结点

node1->next=node; //设置关键结点指向新插入结点

}else{

free(node);//释放内存

printf("未找到插入位置!");

}

return head;//返回头指针

}

ChainListType *ChainListFind(ChainListType *head,char *key) //按关键字在链表中查找内容

{

ChainListType *h;

h=head; //保存链表头指针

while(h) //若结点有效,则进行查找

{

if(strcmp(h->data.key,key)==0) //若结点关键字与传入关键字相同

return h; //返回该结点指针

h=h->next; //处理下一结点

}

return NULL; //返回空指针

}

int ChainListDelete(ChainListType *head,char *key)

{

ChainListType *node,*h; //node保存删除结点的前一结点

node=h=head;

while(h)

{

if(strcmp(h->data.key,key)==0) //找到关键字,执行删除操作

{

node->next=h->next; //使前一结点指向当前结点的下一结点

free(h); //释放内存

return 1;

}else{

node=h; //指向当前结点

h=h->next; //指向下一结点

}

}

return 0;//未删除

}

int ChainListLength(ChainListType *head)//获取链表结点数量

{

ChainListType *h;

int i=0;

h=head;

while(h) //遍历整个链表

{

i++; //累加结点数量

h=h->next;//处理下一结点

}

return i;//返回结点数量

}

3、操作的测试

#include

typedef struct

{

char key[15]; //关键字

char name[20];

int age;

}DATA; //数据结点类型

void ChainListAll(ChainListType *head) //遍历链表

{

ChainListType *h;

DATA data;

h=head;

printf("链表所有数据如下:");

while(h) //循环处理链表每个结点

{

data=h->data;//获取结点数据

printf("(%s,%s,%d)",data.key,data.name,data.age);

h=h->next;//处理下一结点

}

return;

}

int main()

{

ChainListType *node, *head=NULL;

DATA data;

char key[15],findkey[15];

printf("输入链表中的数据,包括关键字、姓名、年龄,关键字输入0,则退出:");

do{

fflush(stdin); //清空输入缓冲区

scanf("%s",data.key);

if(strcmp(data.key,"0")==0) break; //若输入0,则退出

scanf("%s%d",data.name,&data.age);

head=ChainListAddEnd(head,data);//在链表尾部添加结点数据

}while(1);

printf("该链表共有%d个结点。",ChainListLength(head)); //返回结点数量

ChainListAll(head); //显示所有结点

printf("插入结点,输入插入位置的关键字:") ;

scanf("%s",&findkey);//输入插入位置关键字

printf("输入插入结点的数据(关键字 姓名 年龄):");

scanf("%s%s%d",data.key,data.name,&data.age);//输入插入结点数据

head=ChainListInsert(head,findkey,data);//调用插入函数

ChainListAll(head); //显示所有结点

printf("在链表中查找,输入查找关键字:");

fflush(stdin);//清空输入缓冲区

scanf("%s",key);//输入查找关键字

node=ChainListFind(head,key);//调用查找函数,返回结点指针

if(node)//若返回结点指针有效

{

data=node->data;//获取结点的数据

printf("关键字%s对应的结点数据为(%s,%s,%d)" ,key,data.key,data.name,data.age);

}else//若结点指针无效

printf("在链表中未找到关键字为%s的结点!",key);

printf("在链表中删除结点,输入要删除的关键字:");

fflush(stdin);//清空输入缓冲区

scanf("%s",key);//输入删除结点关键字

ChainListDelete(head,key); //调用删除结点函数

ChainListAll(head); //显示所有结点

getch();

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验 一 线性的基本操作实现及其应用 一、实验目的 1、熟练掌握线性的基本操作在两种存储结构上的实现。 2、会用线性链表解决简单的实际问题。 二、实验内容 题目一 链表基本操作 该程序的功能是实现单链表的定义和操作。该程序包括单链表结构类型以及对单链表操 作的具体的函数定义和主函数。其中,程序中的单链表(带头结点)结点为结构类型, 结点值为整型。单链表操作的选择以菜单形式出现,如下所示: please input the operation: 1.初始化 2.清空 3.求链表长度 4.检查链表是否为空 5.检查链表是否为满 6.遍历链表(设为输出元素)7.从链表中查找元素 8.从链表中查找与给定元素值相同的元素在中的位置 9.向链表插入元素 10. 从链表删除元素 其他键退出。。。。。 题目二 约瑟夫环问题 设编号为1,2,3,……,n的n(n>0)个人按顺时针方向围坐一圈,每个人持有一个正整数 密码。开始时任选一个正整数做为报数上限m,从第一个人开始顺时针方向自1起顺序报 数,报到m时停止报数,报m的人出列,将他的密码作为新的m值,从他的下一个人开始重 新从1报数。如此下去,直到所有人全部出列为止。令n最大值取30。要求设计一个程序 模拟此过程,求出出列编号序列。 struct node //结点结构 { int number; /* 人的序号 */ int cipher; /* 密码 */ struct node *next; /* 指向下一个节点的指针 */ }; 三.实验步骤 题目一 链表基本操作 (一)、数据结构与核心算法设计描述 1、单链表的结点类型定义 /* 定义DataType为int类型 */ typedef int DataType; /* 单链表的结点类型 */ typedef struct LNode { DataType data; struct LNode *next; }LNode,*LinkedList; 2、初始化链表 LinkedList LinkedListInit() { //函数功能:对链表进行初始化 参数:链表(linklist L) 成功初始化返回1,否则返回0 } 3、清空单链表 void LinkedListClear(LinkedList &L) {//函数功能:把链表清空 参数:链表(linklist L) 成功清空链表返回1 } 4、 检查单链表是否为空 int LinkedListEmpty(LinkedList L) { //函数功能:判断链表是否为空 参数:链表(linklist L) 链表为空时返回0,不为空返回1 } 5、 遍历单链表 void LinkedListTraverse(LinkedList L) { //函数功能:遍历链表,输出每个节点的elem值 参数:链表(linklist L) 通过循环逐个输出节点的elem值 } 6、 求单链表的长度 int LinkedListLength(LinkedList L) { //函数功能:返回链表的长度 参数:链表(linklist L) 函数返回链表的长度 } 7、 从单链表中查找元素 LinkedList LinkedListGet(LinkedList L,int i) { //函数功能: 从链表中查找有无给定元素 参数;链表(linklist L),给定元素(int i) 如果链表中有给定元素(i)则返回1,否则返回0 } 8、从单链表中查找与给定元素值相同的元素在链表中的位置 LinkedList LinkedListLocate(LinkedList L, DataType x) {//函数功能: 从链表中查找给定元素的位置 参数;链表(linklist L),给定元素(int i) 如果链表中有给定元素i则返回元素的位置, 没有则返回0 } 9、 向单链表插入元素 void LinkedListInsert(LinkedList &L,int i,DataType x) { // L 为带头结点的单链表的头指针,本算法 // 在链表中第i 个结点之前插入新的元素 x } 10、 从单链表删除元素 void LinkedListDel(LinkedList &L,DataType x) { 删除以 L 为头指针的单链表中第 i 个结点 } (二)、函数调用及主函数设计 zhujiemian(); cin>>a; do { switch(a) { case 1: if(init(L)==1) cout<<"成功初始化!"<<endl; else cout<<"初始化失败!"<<endl; break; case 2: if(makeempty(L)==1) cout<<"链表

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值