数据结构线性表基本操作

  • 基本内容
  • 线性表的顺序表示和实现
    • 线性表的顺序存储表示
    • 顺序表中基本操作的实现
      • 1、顺序表的初始化
      • 2、取值
      • 3、查找
      • 4、插入
      • 5、删除
  • 线性表的链式表示和实现
    • 单链表的定义和表示
    • 单链表基本操作的实现
      • 1、初始化
      • 2、取值
      • 3、查找
      • 4、插入
      • 5、 删除
      • 6、创建单链表
        • 头插法创建单链表
        • 尾插法创建单链表
  • 线性表的应用
    • 线性表的合并
    • 有序表的合并
      • 顺序有序表的合并
      • 链式有序表
  • 结语

基本内容

因为第一次数据结构阶段考手写代码又想规范写又写不出规范的可读性强的代码,让我第一次意识到自己应该在这方面下一些功夫。这篇文章是记录自己把书上写的算法打到电脑上遇到的问题。

线性表的顺序表示和实现

线性表的顺序存储表示

将书中代码复刻如下:

#define MAXSIZE 100//顺序表可能达到的最大长度
typedef struct
{ElemType *elem;//储存空间的基地址int length;//当前长度
}SqList;//顺序表的结构类型为SqList

这敲到电脑上当然不能直接运行啦,哈哈,ElemType只是任意的元素类型,自己改一下就好。我这里就直接用int了。
改后如下:

#define MAXSIZE 100//顺序表可能达到的最大长度
typedef struct
{int *elem;//储存空间的基地址int length;//当前长度
}SqList;//顺序表的结构类型为SqList

顺序表中基本操作的实现

1、顺序表的初始化

将书中代码复刻如下:

Status InitList(SqList &L)
{//构造一个空的顺序表LL.elem=new ElemType[MAXSIZE];//为顺序表分配一个大小为MAXSIZE的数组空间if(!L.elem)exit(overflow_error);//存储分配失败退出L.length=0;//空表长度为0return OK;
}

这里遇到了几个问题:
第一,c语言是没有new的用法的
第二,c语言中没有按引用传参&,应改为地址引用*
第三,“.”和“->”是有区别的,如果L是一个结构体指针就用“->”,如果是正常结构体就用“.”
第四,exit(OVERFLOW)这个OVERFLOW应该是得提前定义个数值的。应该有很多小伙伴不知道exit跟return有啥区别,我就附在这后面了,exit用于在程序运行的过程中随时结束程序,return( )是当前函数的返回,直接说就是exit运行整个程序就结束了,return运行return所在函数结束。
改后如下:

#define OVERFLOW 0
#define OK 1
int InitList(SqList *L)
{//构造一个空的顺序表LL->elem=(int *)malloc(MAXSIZE*sizeof(int));//为顺序表分配一个大小为MAXSIZE的数组空间if(!L->elem)exit(OVERFLOW);//存储分配失败退出L->length=0;//空表长度为0return OK;
}

2、取值

将书中代码复刻如下:

Status GetElem(SqList L,int i,int &e)
{if(i<1||i>L.length)return ERROR;//判断i值是否合理e=L.elem[i-1];//elem[i-1]单元存储第i个数据元素return OK;
}

这里基本上没咋改,就把ERROR换成了OVERFLOW省得再define一次,其实直接return 0也一样。
改后如下:

int GetElem(SqList L,int i,int *e)
{if(i<1||i>L.length)return OVERFLOW;//判断i值是否合理e=L.elem[i-1];//elem[i-1]单元存储第i个数据元素return OK;
}

3、查找

将书中代码复刻如下:

int LocateElem(SqList L,ElemType e)
{//在顺序表L中查找值为e的数据元素,返回其序号for(i=0;i<L.length;i++)if(L.elem[i]==e)return i+1;//查找成功,返回序号i+1return 0;//查找失败,返回0
}

这里就 i 没定义
改后如下:

int LocateElem(SqList L,int e)
{//在顺序表L中查找值为e的数据元素,返回其序号int i;for(i=0;i<L.length;i++)if(L.elem[i]==e)return i+1;//查找成功,返回序号i+1return 0;//查找失败,返回0
}

4、插入

将书中代码复刻如下:

Status ListInsert(SqList &L,int i,ElemType e)
{//在顺序表L中第i个位置插入新的元素e,i的值的合法范围是1<=i<=L.length+1if((i<1)||(i>L.length+1))return ERROR;//i值不合法if(L.length==MAXSIZE)return ERROR;//当前存储空间已满for(j=L.length-1;j>=i-1;j--)L.elem[j+1]=L.elem[j];//插入位置之后的元素后移L.elem[i-1]=e;//将新元素e放入第i个位置++L.length;//表长加1return OK;
}

改后如下:

int ListInsert(SqList *L,int i,int e)
{//在顺序表L中第i个位置插入新的元素e,i的值的合法范围是1<=i<=L.length+1if((i<1)||(i>L->length+1))return OVERFLOW;//i值不合法if(L->length==MAXSIZE)return OVERFLOW;//当前存储空间已满int j;for(j=L->length-1;j>=i-1;j--)L->elem[j+1]=L->elem[j];//插入位置之后的元素后移L->elem[i-1]=e;//将新元素e放入第i个位置++L->length;//表长加1return OK;
}

5、删除

Status ListDelete(SqList &L,int i)
{//在顺序表L中删除第i个元素,i值的合法范围是1<=i<=L.lengthif((i<1)||(i>L.length))return ERROR;//i值不合法for(j=i;j<=L.length-1;j++)L.elem[j-1]=L.elem[j];//被删除元素之后的元素前移--L.length;//表长减1return OK;
}

改后如下:

int ListDelete(SqList *L,int i)
{//在顺序表L中删除第i个元素,i值的合法范围是1<=i<=L.lengthif((i<1)||(i>L->length))return OVERFLOW;//i值不合法int j;for(j=i;j<=L->length-1;j++)L->elem[j-1]=L->elem[j];//被删除元素之后的元素前移--L->length;//表长减1return OK;
}

主函数传参如下:
注:主函数我用的&大家不要混淆,这里只是单纯的表示取地址操作。

int main()
{int i,e;SqList L;InitList(&L);GetElem(L,i,&e);LocateElem(L,e);ListInsert(&L,i,e);ListDelete(&L,i);return 0;
}

线性表的链式表示和实现

单链表的定义和表示

将书上代码复刻如下:

typedef struct LNode
{ElemType data;//结点的数据域struct LNode *next;//结点的指针域
}LNode,*LinkList;//LinkList为指向结构体LNode的指针类型

改后如下:

typedef struct LNode
{int data;//结点的数据域struct LNode *next;//结点的指针域
}LNode,*LinkList;//LinkList为指向结构体LNode的指针类型

单链表基本操作的实现

1、初始化

将书上代码复刻如下:

Status InitList(LinkList &L)
{//构造一个空的单链表LL=new LNode;//生成新结点作为头结点,用头指针L指向头结点L->next=NULL;//头结点的指针域置空return OK;
}

前面有提到c语言不能用引用传参&和new,这大家应该能理解了,然后为什么不加星呢?因为LinkList为指向结构体LNode的指针类型,用LNode*也是可以的。
改后如下:

int InitList(LinkList L)
{//构造一个空的单链表LL=(LNode*)malloc(sizeof(LNode));//生成新结点作为头结点,用头指针L指向头结点L->next=NULL;//头结点的指针域置空return OK;
}

2、取值

将书中代码复刻如下:

Status GetElem(LinkList L,int i,ElemType &e)
{//在带头结点的单链表L中根据序号i获取元素的值,用e返回L中第i个数据元素的值p=L->next;j=1;//初始化,p指向首元结点,计数器j初值为1while(p&&j<i)//顺链域向后扫描,直到p为空或p指向第i个元素{p=p->next;//p指向下一个结点++j;//计数器j相应加1}if(!p||j>i)return ERROR;//i值不合法i>n或i<=0e=p->data;//取第i个结点的数据域return OK;
}

改后如下:

int GetElem(LinkList L,int i,int *e)
{//在带头结点的单链表L中根据序号i获取元素的值,用e返回L中第i个数据元素的值LinkList p;int j;p=L->next;j=1;//初始化,p指向首元结点,计数器j初值为1while(p&&j<i)//顺链域向后扫描,直到p为空或p指向第i个元素{p=p->next;//p指向下一个结点++j;//计数器j相应加1}if(!p||j>i)return ERROR;//i值不合法i>n或i<=0e=p->data;//取第i个结点的数据域return OK;
}

3、查找

将书上代码复刻如下:

LNode* LocateElem(LinkList L,ElemType e)
{//在带头结点的单链表L中查找值为e的元素p=L->next;//初始化,p指向首元结点while(p&&p->data!=e)//顺链域向后扫描,直到p为空或p所指结点的数据域等于ep=p->next;//p指向下一个结点return p;//查找成功则返回值为e的结点地址p,查找失败p为NULL
}

改后如下:

LNode* LocateElem(LinkList L,int e)
{//在带头结点的单链表L中查找值为e的元素LinkList p;p=L->next;//初始化,p指向首元结点while(p&&p->data!=e)//顺链域向后扫描,直到p为空或p所指结点的数据域等于ep=p->next;//p指向下一个结点return p;//查找成功则返回值为e的结点地址p,查找失败p为NULL
}

4、插入

将书中代码复刻如下:

Status ListInsert(LinkList &L,int i,ElemType e)
{//在带头结点的单链表L中第i个位置插入值为e的新结点p=L;j=0;while(p&&(j<i-1)){p=p->next;++j;//查找第i-1个结点,p指向该结点}if(!p||j>i-1)return ERROR;//i>n+1或者i<1s=new LNode;s->data=e;s->next=p->next;p->next=s;return OK;
}

改后如下:

int ListInsert(LinkList L,int i,int e)
{//在带头结点的单链表L中第i个位置插入值为e的新结点LinkList p;int j;p=L;j=0;while(p&&(j<i-1)){p=p->next;++j;//查找第i-1个结点,p指向该结点}if(!p||j>i-1)return ERROR;//i>n+1或者i<1LinkList s;s=(LNode*)malloc(sizeof(LNode));s->data=e;s->next=p->next;p->next=s;return OK;
}

5、 删除

将书中代码复刻如下:

Status ListDelete(LinkList &L,int i)
{//带头结点的单链表L中,删除第i个元素p=L;j=0;while((p->next)&&(j<i-1))//查找第i-1个结点,p指向该结点{p=p->next;++j;}if(!(p->next)||(j>i-1))return ERROR;//当i>n或i<1时,删除位置不合理q=p->next;//临时保存被删结点的地址以备释放p->next=q->next;//改变删除结点前驱结点的指针域delete q;//释放删除结点的空间return OK;
}

改后如下:
注:C语言没有delete,这是C++中的释放空间的方法,C语言中是用free()函数释放空间的,free()在stdlib.h中声明

int ListDelete(LinkList L,int i)
{//带头结点的单链表L中,删除第i个元素LinkList p,q;int j;p=L;j=0;while((p->next)&&(j<i-1))//查找第i-1个结点,p指向该结点{p=p->next;++j;}if(!(p->next)||(j>i-1))return ERROR;//当i>n或i<1时,删除位置不合理q=p->next;//临时保存被删结点的地址以备释放p->next=q->next;//改变删除结点前驱结点的指针域free(q);//释放删除结点的空间return OK;
}

6、创建单链表

头插法创建单链表

将书中代码复刻如下:

void CreateList_H(LinkList &L,int n)
{//逆位序输入n个元素的值,建立带表头结点的单链表LL=new LNode;L->next=NULL;//先建立一个带头结点的空链表for(i=0;i<n;i++){p=new LNode;scanf("%d",&p->data);p->next=L->next;L->next=p;//将新结点插入到头结点之后}
}

改后如下:

void CreateList_H(LinkList L,int n)
{//逆位序输入n个元素的值,建立带表头结点的单链表LL=(LNode*)malloc(sizeof(LNode));L->next=NULL;//先建立一个带头结点的空链表int i;for(i=0;i<n;i++){LinkList p;p=(LNode*)malloc(sizeof(LNode));scanf("%d",&p->data);p->next=L->next;L->next=p;//将新结点插入到头结点之后}
}

尾插法创建单链表

将书中代码复刻如下:

void CreateList_R(LinkList &L,int n)
{//正位序输入n个元素的值,建立带头结点的单链表LL=new LNode;L->next=NULL;//先建立一个带头结点的空链表r=L;//尾指针r指向头结点for(i=0;i<n;i++){p=new LNode;//生成新结点scanf("%d",&p->data);p->next=NULL;r->next=p;//将新结点插入到尾结点之后r=p;//指向新的尾结点}
}

改后如下:

void CreateList_R(LinkList L,int n)
{//正位序输入n个元素的值,建立带头结点的单链表LL=(LNode*)malloc(sizeof(LNode));L->next=NULL;//先建立一个带头结点的空链表LinkList r;r=L;//尾指针r指向头结点int i;for(i=0;i<n;i++){LinkList p;p=(LNode*)malloc(sizeof(LNode));//生成新结点scanf("%d",&p->data);p->next=NULL;r->next=p;//将新结点插入到尾结点之后r=p;//指向新的尾结点}
}

线性表的应用

线性表的合并

int ListLength(LNode L)
{int i=0;LinkList p;p=L.next;while(p){i++;p=p->next;}return i;
}
void MergeList(LinkList LA,LNode LB)
{int m,n,i,e;
m=ListLength(*LA);n=ListLength(LB);//求线性表的长度
for(i=1;i<=n;i++)
{GetElem(&LB,i,e);//取LB中第i个数据元素赋给eif(!LocateElem(LA,e))//LA中不存在和e相同的数据元素ListInsert(LA,++m,e);//将e插在LA的最后
}
}

有序表的合并

顺序有序表的合并

void MergeList_Sq(SqList LA,SqList LB,SqList *LC)
{//已知顺序有序表LA和LB的元素按值非递减排列//归并LA和LB得到新的顺序有序表LC,LC的元素也按值非递减排列LC->length=LA.length+LB.length;//新表长度为待合并的两表长度之和LC->elem=(int *)malloc(LC->length*sizeof(int));//为合并后的新表分配一个数组空间int *pa,*pb,*pc,*pa_last,*pb_last;pc=LC->elem;//指针pc指向新表的第一个元素pa=LA.elem;pb=LB.elem;//指针pa,pb的初值分别指向两个表的第一个元素pa_last=LA.elem+LA.length-1;//指针pa_last指向LA的最后一个元素pb_last=LB.elem+LB.length-1;//指针pb_last指向LB的最后一个元素while((pa<=pa_last)&&(pb<=pb_last))//LA,LB均未达表尾{if(*pa<=*pb)*pc++=*pa++;//依此“摘取”两表中值较小的结点插入到LC的最后else *pc++=*pb++;}while(pa<=pa_last)*pc++=*pa++;//LB达表尾,将LA剩余元素插入LC的最后while(pb<=pb_last)*pc++=*pb++;//LA达表尾,将LB剩余元素插入LC的最后
}

链式有序表

void MergeList_L(LinkList LA,LinkList LB,LinkList LC)
{//已知单链表LA和LB的元素按值非递减排列//归并LA和LB得到新的单链表LC,LC的元素也按值非递减排列LinkList pa,pb,pc;pa=LA->next;pb=LB->next;//pa,pb的初值分别指向两个表的第一个元素LC=LA;//LA的头结点作为LC的头结点pc=LC;//pc的初值指向LC的头结点while(pa&&pb){//LA和LB均未达表尾,依此“摘取”两表中值较小的结点插入到LC的最后if(pa->data<=pb->data)//“摘取”pa所指结点{pc->next=pa;pc=pa;pa=pa->next;}else//“摘取”pb所指结点{pc->next=pb;pc=pb;pb=pb->next;}}pc->next=pa?pa:pb;//将非空表的剩余段插入到pc所指的结点之后free(LB);
}

结语

第一次写博客,感觉还不错,对知识的一个熟悉有很大帮助。如果大家也是学生,推荐把书上的算法描述自己照着打一遍,当然打完一遍只是对这些算法有个初步的理解,自己还得多看看。另外,如果有什么建议或者我有什么错误随时欢迎各位大佬批评指正,非常感谢。下一章,栈和队列

数据结构线性表基本操作相关推荐

  1. 数据结构—线性表(第三章)—基本知识点总结

    目录 1. 线性表的定义 2. 线性表的抽象数据类型 3.线性表的顺序存储结构 3.1 顺序存储定义 3.2 顺序存储方式 3.3 数据长度与线性表长度区别 3.4 地址计算方法 4. 顺序存储结构的 ...

  2. 数据结构——线性表(三)

    数据结构--线性表(三) 作者:黑衣侠客 一.线性表的定义 线性表,从名字来看,可以发现,是具有像线一样性质的表 线性表:零个或多个数据元素的有限序列. 首先,它是一个序列,也就是说,元素之间是有顺序 ...

  3. c语言构造一个空线性表l,数据结构线性表顺序结构的定义与实现C语言-Go语言中文社区...

    大家好,今天给大家总结了一下数据结构里面的线性表的顺序结构,顺序表表示的是用一组地址连续的存储单元依次存储线性表的数据元素,所以顺序结构的实现一般采用数组的方式来实现,存储空间也采用动态分配的方式.在 ...

  4. 数据结构——线性表(2)

    上接 数据结构--线性表(1) 上文中介绍了线性表的顺序存储结构和单链表的介绍与代码实现,接下来,继续介绍线性表的链式存储 循环链表   在座的各位都很年轻,不会觉得日月如梭.可上了点年纪的人,比如我 ...

  5. 数据结构-线性表之用队列实现栈用栈实现队列

    文章目录 **********用队列实现栈 一:思路 二:实现 (1)结构体定义 (2)初始化和销毁 (3)进"栈" (4)出"栈" 三:代码 ******** ...

  6. 数据结构-线性表之带头结点的双向循环链表

    文章目录 前言 实现 (1)结构定义 (2)基本函数 (3)操作实现 测试 代码 前言 链表的类型有很多种(根据带头或不带头,循环或非循环等等),但是我们重点研究的只有两种,一种结构非常简单是无头单向 ...

  7. 数据结构摧毁线性表用c语言,[简述]数据结构-线性表(c语言实现)

    [简述]数据结构-线性表(c语言实现)second60 20180422 1. 线性表的定义 线性表是具有相同特性的数据元素的一个有限序列. 2. 线性表抽象数据类型描述 ADT  List { 数据 ...

  8. 王道数据结构线性表:有读者认为直接去掉p结点会造成断链?

    王道数据结构线性表:有读者认为直接去掉p结点会造成断链? 我用图解的方式来说明一下,文字有点多,看起来比较眼疼,但是内容不多,希望能对你有帮助. 书上的代码 解释 (ps:对上面解释的一点补充↓)

  9. 数据结构-线性表(严书代码实现)

    数据结构-线性表的顺序表示代码 //头文件内容实现 #ifndef SEQLIST_H_INCLUDED #define SEQLIST_H_INCLUDED #include<string.h ...

最新文章

  1. python 投票脚本_使用Python脚本拉取2014 CSDN博客之星投票情况
  2. 如何将VMware ubuntu虚拟机磁盘增长改成自分配(未成功)
  3. python类库32[多进程同步Lock+Semaphore+Event]
  4. 7 centos 修改磁盘uuid_Centos7修改分区空间
  5. CI框架源码阅读笔记7 配置管理组件 Config.php
  6. 深入理解Sqlserver索引
  7. 《OpenStack云计算实战手册(第2版)》——1.7 添加用户
  8. Nature Reviews Cancer综述:长非编码RNA在肿瘤转移中的作用
  9. [CQOI2017]小Q的棋盘
  10. rocketmq技术内幕 pdf_618买什么也别忘了买书!精选100+本技术好书和思维导图,建议收藏!...
  11. HCIE-Security Day32:IPSec:深入学习ipsec ikev1、主模式、野蛮模式、快速模式、dh算法、预共享密钥
  12. mysql8.0和phpmyadmin_MySQL 8.0上的phpMyAdmin?mysql-问答-阿里云开发者社区-阿里云
  13. boblog任意变量覆盖漏洞(二)
  14. vue前端信息详情页模板梳理
  15. 串口调试更方便-安卓串口调试工具(附底层USB源码)
  16. javalinux服务器上写文件,java 读取linux服务器上文件
  17. PTA 数据结构与算法题目集(中文)7-38 寻找大富翁(25 分)快排或堆排序
  18. 机器人动力学与控制学习笔记(七)————基于计算力矩法的滑模控制
  19. 魔兽7.0服务器维护时间,关于魔兽7.0版本你一定要知道的60条注意事项
  20. Enterprise Architect教程

热门文章

  1. 公司让给客户发国庆祝福短信怎么快速完成
  2. 魔兽怀旧服服务器紧急维护,《魔兽世界怀旧服》这些服务器不会排队!官方紧急公告开服排队约10小时...
  3. Mac 根目录下创建文件夹
  4. Python——sqlalchemy.exc.ArgumentError
  5. python怎么输入分数_在python中怎么表示分数
  6. 第七章 实现炫酷效果—图像和动画(2)
  7. 将MacbookPro作为电脑音箱的方法
  8. Flash CS4 序列号过期打不开处理方法
  9. 基于 Flink 构建大规模实时风控系统在阿里巴巴的落地
  10. 【面向对象-05】什么是类变量、实例变量、以及区别