热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【2.1】顺序表

第二章序言上一章的两节介绍了常用的算法,这些算法用来处理零散的数据。实际上我们有时候处理的数据之间是存在一种或者多种特定的关系时,我们称这些关系为结构

第二章序言

上一章的两节介绍了常用的算法,这些算法用来处理零散的数据。实际上我们有时候处理的数据之间是存在一种或者多种特定的关系时,我们称这些关系为结构。通常数据之间有三种基本的机构。

(1)线性结构:数据元素之间为一对一的关系。

(2)树形结构:数据元素之间为一对多的关系。

(3)网状结构:数据元素之间为多对多的关系。


什么是线性表?

线性表示最基本、最简单、也是最常用的一种数据结构。它是一个含有n个节点的有限序列,不同线性表的数据元素可以不痛,但是对于同一个线性表,各个数据元素必须有相同的数据类型,即同一线性表中各个数据元素具有相同的数据类型,每个数据元素的长度相同。

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

a、有且只有一个首元素

b、有且只有一个末元素

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

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

顺序表是用一组地址连续的存储单元依次保存线性表中的数据元素,由于它使用这种存储结构,使得程序中可以很容易的访问顺序表中的任何元素,也可以方便的将数据元素添加到顺序表的末尾。

顺序表有什么结构特征?

1、采用一组地址连续的存储单元来存储数据

2、表的存储容量长度不易改变

3、可以随机查找

4、可频繁访问元素

5、不适用于元素的频繁增删操作


项目代码案例,项目结构如下:

文件1:Utils.h

#ifndef _YELER_082_02
#define _YELER_082_02
typedef int ElemType;
typedef int Status;
typedef void MyVoid;
typedef void MyVoid;
typedef int ElemType;
typedef int Status;
typedef struct
{ElemType * elem; //存储空间基址int length; //当前实际使用长度int listsize; //当前分配存储容量
}SqList;
//比较函数的声明
Status compare(ElemType e1, ElemType e2);MyVoid visit(ElemType e, ElemType i);#endif
文件二:method.h

#ifndef _YELER_082_01
#define _YELER_082_01
#include "Utils.h"
Status Init(SqList &L);//构造一个空的线性表Status Destory(SqList &L);//销毁线性表LStatus ClearList(SqList &L);//将L表重置为空表Status ListEmpty(SqList L);//判断L表是否为空Status ListLength(SqList L);//返回L表中数据元素的长度Status ListInsert(SqList &L, ElemType i, ElemType e);//向表中的第i个位置插入元素eStatus GetElem(SqList L,ElemType i,ElemType &e);//取出L表中指定位置的元素Status LocateElem(SqList L,ElemType e, Status(*compare)(ElemType, ElemType));//找出在L表中第一个与e匹配的元素Status PriorElem(SqList L,ElemType cur_e,ElemType &pre_e);//找出当前元素cur_e的前驱pre_eStatus NextElem(SqList L,ElemType cur_e,ElemType &next_e);//找出当前元素cur_e的后继next_eStatus ListDelete(SqList &L,ElemType i,ElemType &e);//删除表中第i个位置的元素eStatus ListTraverse(SqList L, MyVoid(*visit)(ElemType,ElemType));//遍历表中的每个元素在visit函数中执行一遍Status ListSort(SqList &L);//对链表中的数据排序,从小到大MyVoid MergeList_Sq(SqList La, SqList Lb, SqList &Lc); //已知线性表La和Lb,归并La和Lb的到线性表Lc,Lc的元素按照非递减排列
#endif
文件3:Utils.cpp

#include
typedef int ElemType;
typedef int Status;typedef void MyVoid;//比较的工具函数
Status compare(ElemType e1, ElemType e2)
{if (e1 == e2)return true;//在C++中有bool类型的定义,C语言中是没有的return false;}//输出的工具函数
MyVoid visit(ElemType e,ElemType i)
{printf("第%d个元素是%d\n", i, e);
}
文件4:method.cpp

#include
#include
#include "Utils.h"#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量
#define LISTINCREMENT 10 //线性表存储空间的分配增量
#define OK 1
#define TRUE 1
#define FALSE 0
#define NOTEXIST 0
#define OVERFLOW -1
#define ERROR -2//构造一个空的线性表
Status Init(SqList &L)
{L.elem = (ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));//给线性表分配初始空间400个字节if (!L.elem){exit(OVERFLOW);}L.length = 0;//指定实际长度为0,存的数据个数L.listsize = LIST_INIT_SIZE;//指定分配空间长度return OK;
}//销毁线性表L
Status Destory(SqList &L)
{if (!L.elem)//如果线性表为空,返回错误码{return ERROR;}free(L.elem);return OK;
}//将L表重置为空表
Status ClearList(SqList &L)
{if (!L.elem){return ERROR;}L.length = 0;return OK;
}//判断L表是否为空
Status ListEmpty(SqList L)
{if (!L.elem){return ERROR;}if (L.length!=0){return TRUE;}return FALSE;
}//返回L表中数据元素的长度
Status ListLength(SqList L)
{if (!L.elem){return ERROR;}return L.length;
}//取出L表中指定位置的元素
Status GetElem(SqList L, ElemType i, ElemType &e)
{if (!L.elem){return ERROR;}if (i<1 || i>L.length &#43; 1){return ERROR;}e&#61; L.elem[i-1];return OK;
}//找出在L表中第一个与e匹配的元素,第三个参数是指向比较函数的指针
Status LocateElem(SqList L, ElemType e, Status(*compare)(ElemType, ElemType))
{//在顺序线性表L中查找第1个值与e满足compare()的元素的为序//若找到&#xff0c;则返回其在L中的位序&#xff0c;否则返回0int i &#61; 1;//i的初值为第1个元素的位序ElemType *p &#61; L.elem;//定义一个指针指向线性表的起始位置while (i<&#61;L.length&&!(*compare)(*p&#43;&#43;,e))//线性表的数据在长度范围内没有找到相同的数值&#xff0c;位置以此后移{i&#43;&#43;;}if (i<&#61;L.length){return i;//返回的是在第几个位置的元素}else{return NOTEXIST;}
}//找出当前元素cur_e的前驱pre_e
Status PriorElem(SqList L, ElemType cur_e, ElemType &pre_e)
{ElemType *p &#61; NULL,i&#61;1;p &#61; L.elem;//定义一个指针指向头结点if (!L.elem){return ERROR;}if (*p&#61;&#61;cur_e)//如果当前被找的参照物为第一个节点&#xff0c;那么返回错误{return ERROR;}//遍历找到当前的节点所在的位置while (i<&#61;L.length){if (*p&#61;&#61;cur_e){pre_e &#61; *(p - 1); break;}i&#43;&#43;;p&#43;&#43;;}if (i <&#61; L.length){return OK;}else{return NOTEXIST;}
}//找出当前元素cur_e的后继next_e
Status NextElem(SqList L, ElemType cur_e, ElemType &next_e)
{ElemType *p &#61; NULL,i&#61;0;p &#61; L.elem;//当传递过来的线性表为空&#xff0c;或者ElemType cur_e为最后的一个节点的时候&#xff0c;返回错误值if (!p||cur_e&#61;&#61;L.elem[L.length-1])//数组表示是从零开始&#xff0c;L.elem[L.length-1]代表线性表中的最后一个元素{return ERROR;}while (i<&#61;L.length){if (cur_e&#61;&#61;*p){next_e &#61; *(p &#43; 1); break;}i&#43;&#43;;p&#43;&#43;;}if (i <&#61; L.length){return OK;}else{return NOTEXIST;}
}//向表中的第i个位置插入元素e
Status ListInsert(SqList &L, ElemType i, ElemType e)
{ElemType *newbase &#61; NULL, *q &#61; NULL, *p &#61; NULL;if (!L.elem){return ERROR;}if (i<1 || i>L.length &#43; 1){return ERROR;}if (L.length >&#61; L.listsize){newbase &#61; (ElemType*)realloc(L.elem, (L.listsize &#43; LISTINCREMENT)*sizeof(ElemType));if (!newbase){exit(OVERFLOW);}L.elem &#61; newbase;//新基址L.listsize &#43;&#61; LISTINCREMENT;}q &#61; &(L.elem[i - 1]);//得到要插入元素的地址//插入之后的元素位置后移for (p &#61; &(L.elem[L.length - 1]); p >&#61; q; --p){*(p &#43; 1) &#61; *p;}*q &#61; e;&#43;&#43;L.length;return OK;
}//删除表中第i个位置的元素e
Status ListDelete(SqList &L, ElemType i, ElemType &e)
{ElemType *p &#61; NULL,*q&#61; NULL,t&#61;1;p &#61; L.elem;if (!L.elem){return ERROR;}if (i<1||i>L.length&#43;1){return ERROR;}//删除涉及到移位操作p &#61; &L.elem[i];//获取需要删除的元素的地址e &#61; *p;//将被删除的数据放置到变量中&#xff0c;不能放到下方&#xff0c;因为指针的位置变了q &#61; L.elem &#43; L.length - 1;//q是指向表尾节点的指针for (&#43;&#43;p; p <&#61;q ; p&#43;&#43;){*(p - 1) &#61; *(p);}L.length--;return OK;
}//遍历表中的每个元素在visit函数中执行一遍typedef void MyVoid;
Status ListTraverse(SqList L, MyVoid(*visit)(ElemType, ElemType))
{ElemType *p &#61; NULL,i;p &#61; L.elem;for (i &#61; 1; i <&#61;L.length; i&#43;&#43;,p&#43;&#43;){(*visit)(*p,i);}return OK;
}//对链表中的数据排序&#xff0c;从小到大&#xff0c;采用冒泡排序法
Status ListSort(SqList &L)
{ElemType *p &#61; NULL, i, j;ElemType temp;for ( i &#61; 0; i L.elem[j&#43;1]){temp &#61; L.elem[j];L.elem[j ] &#61; L.elem[j&#43;1];L.elem[j&#43;1] &#61; temp;}}}return OK;
}//已知线性表La和Lb,归并La和Lb的到线性表Lc&#xff0c;Lc的元素按照非递减排列
MyVoid MergeList_Sq(SqList La, SqList Lb, SqList &Lc)
{ElemType *pa &#61; NULL, *pb &#61; NULL, *pc &#61; NULL;ElemType *pa_last &#61; NULL, *pb_last &#61; NULL;pa &#61; La.elem, pb &#61; Lb.elem;Lc.listsize &#61; Lc.length &#61; La.length &#43; Lb.length;pc &#61; Lc.elem &#61; (ElemType*)malloc(Lc.listsize*sizeof(ElemType));//为pc申请空间if (!Lc.elem) exit(OVERFLOW);//存储分配失败pa_last &#61; La.elem &#43; La.length - 1;//获取线性表La的最后一个元素的指针pb_last &#61; Lb.elem &#43; Lb.length - 1;//获取线性表Lb的最后一个元素的指针while (pa <&#61; pa_last&&pb <&#61; pb_last){if (*pa <&#61; *pb){*pc&#43;&#43; &#61; *pa&#43;&#43;;//*pc &#61; *pa; pc &#61; pc&#43;1; pa &#61; pa&#43;1;}else{*pc&#43;&#43; &#61; *pb&#43;&#43;;}}while (pa<&#61;pa_last){*pc&#43;&#43; &#61; *pa&#43;&#43;;//插入La中的剩余元素}while (pb<&#61;pb_last){*pc&#43;&#43; &#61; *pb&#43;&#43;;//插入Lb中的剩余元素}
}
文件5&#xff1a;main.cpp

#include
#include
#include"method.h"
#include"Utils.h"
int main()
{SqList L,La,Lb,Lc;ElemType i &#61; 0,e&#61;0,*p&#61;NULL,flag;printf("*************线性表的顺序操作**********\n");printf("初始化顺序表:");i&#61;Init(L);printf("%d\n",i);/*printf("————————————————————\n");printf("销毁顺序表:");i &#61; Destory(L);printf("%d\n", i);*//*printf("————————————————————\n");printf("将顺序表置空:");i&#61;ClearList(L);printf("%d\n",i);*//*printf("————————————————————\n");printf("判断顺序表是否为空:");i &#61; ListEmpty(L);printf("%d\n", i);*//*printf("————————————————————\n");printf("输出顺序表的长度:");i&#61;ListLength(L);printf("%d\n", i);*/printf("————————————————————\n");printf("向表中插入元素\n");ListInsert(L, 1, 5);ListInsert(L, 2, 3);ListInsert(L, 1, 1);ListInsert(L, 2, 7);ListInsert(L, 2, 10);printf("插入元素为:");p &#61; L.elem;//这里另外找一个指针专门用来遍历&#xff0c;不要轻易的移动L.elem&#xff0c;否则会对后面的操作造成麻烦for ( i &#61; 0; i %d\n",i);}else{printf("取出L表中7的前驱元素不存在!\n");}printf("————————————————————\n");printf("取出L表中7的后继元素:");flag &#61; NextElem(L, 7, i);if (flag){printf("L表中7的后继元素是-->%d\n", i);}else{printf("取出L表中7的后继元素不存在!\n");}printf("————————————————————\n");printf("删除L表中数值为7元素:\n");ListDelete(L, 3, i);printf("L表中被删除的元素是%d\n", i);printf("————————————————————\n");printf("遍历L表中的元素并打印:\n");ListSort(L);//调用排序函数MyVoid(*Visit)(ElemType, ElemType);//定义一个指向返回空值&#xff0c;含有两个参数&#xff0c;名称为Visit的函数指针Visit &#61; visit;//将函数指针指向一个函数ListTraverse(L, Visit);printf("————————————————————\n");Init(La), Init(Lb);//初始化两个线性表//向线性表中插入数据ListInsert(La, 1, 5);ListInsert(La, 2, 9);ListInsert(La, 3, 4);ListInsert(Lb, 1, 2);ListInsert(Lb, 1, 7);ListInsert(Lb, 1, 1);ListInsert(Lb, 2, 8);ListSort(La), ListSort(Lb);//对线性表进行排序MergeList_Sq(La, Lb, Lc);ListTraverse(Lc, Visit);return 0;
}
运行截图&#xff1a;




推荐阅读
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • web.py开发web 第八章 Formalchemy 服务端验证方法
    本文介绍了在web.py开发中使用Formalchemy进行服务端表单数据验证的方法。以User表单为例,详细说明了对各字段的验证要求,包括必填、长度限制、唯一性等。同时介绍了如何自定义验证方法来实现验证唯一性和两个密码是否相等的功能。该文提供了相关代码示例。 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • 本文介绍了解决Facebook脸书面试题中插入区间的方法,通过模拟遍历的方式判断当前元素与要插入元素的关系,找到插入点并将新区间插入。同时对算法的时间复杂度和空间复杂度进行了分析。 ... [详细]
  • 合并列值-合并为一列问题需求:createtabletab(Aint,Bint,Cint)inserttabselect1,2,3unionallsel ... [详细]
  • 本文介绍了在使用Laravel和sqlsrv连接到SQL Server 2016时,如何在插入查询中使用输出子句,并返回所需的值。同时讨论了使用CreatedOn字段返回最近创建的行的解决方法以及使用Eloquent模型创建后,值正确插入数据库但没有返回uniqueidentifier字段的问题。最后给出了一个示例代码。 ... [详细]
  • Iamtryingtocreateanarrayofstructinstanceslikethis:我试图创建一个这样的struct实例数组:letinstallers: ... [详细]
  • Java编程实现邻接矩阵表示稠密图的方法及实现类介绍
    本文介绍了Java编程如何实现邻接矩阵表示稠密图的方法,通过一个名为AMWGraph.java的类来构造邻接矩阵表示的图,并提供了插入结点、插入边、获取邻接结点等功能。通过使用二维数组来表示结点之间的关系,并通过元素的值来表示权值的大小,实现了稠密图的表示和操作。对于对稠密图的表示和操作感兴趣的读者可以参考本文。 ... [详细]
author-avatar
mobiledu2502871703
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有