《数据结构(C语言版)》严蔚敏代码实现———顺序表
一、前言
最近在重新学习数据结构啦,网上说这本书挺不错哒,于是我开始啃这本书咯...有一说一,严奶奶的书挺好的,就是有点大量使用指针。。。需要沉下心来,看一看画一画才能懂,我自己手敲了一遍书上代码,加上了自己的理解,希望大家也能更清楚的看明白~
好啦废话不多说,下面就上代码!
二、代码
严奶奶的书中预定义了一些预定义常量和类型,大家可以 新建一个y.h文件粘贴以下内容, 然后再去复制代码哦。
y.h文件内容:
/**
* 严奶奶书中的预定义常量和类型
**/
//函数结果状态代码
#define TRUE 1 //成功
#define FALSE 0 //失败
#define OK 1 //成功
#define ERROR 0 //错误
#define INFEASIBLE -1 //不可实行
#define OVERFLOW -2 //溢出
//Status 是函数的类型,其值是函数结果状态代码
typedef int Status;
顺序表SqList.cpp:
#include "y.h"
#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;
typedef int ElemType;
/**
* 严奶奶顺序表的实现
* by 熊子q 2021.1.28
**/
#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量
#define LISTINCREMENT 10 //线性表存储空间的分配增量
//强悍如斯的严奶奶,强悍如斯的顺序表
typedef struct {
ElemType *elem; //存储空间基址
int length; //当前长度
int listsize; //当前分配的存储容量(以sizeof(ElemType)为单位)
}SqList;
//顺序表初始化
Status InitList_Sq(SqList &L){
//构造一个空的线性表L,动态分配空间
L.elem = (ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if(!L.elem) exit(OVERFLOW); //存储空间分配失败
L.length = 0; //空表长度为0
L.listsize = LIST_INIT_SIZE; //初始存储容量
return OK;
}
//销毁线性表,基本操作,书上没有,自己写的
void DestoryList_Sq(SqList &L){
free(L.elem);
//释放后的无效指针必须置为空,不然会导致内存泄漏
L.elem = NULL;
L.length=0;
L.listsize=0;
}
//清空线性表,基本操作,书上没有,自己写的
void ClearList_Sq(SqList &L){
L.length = 0;
}
//判断线性表是否为空,基本操作,书上没有,自己写的
Status ListEmpty_Sq(SqList L){
if(L.length == 0) return TRUE;
else return FALSE;
}
//获取顺序表的长度,基本操作,书上没有,自己写的
int ListLength_Sq(SqList L){
return L.length;
}
//获取元素,基本操作,书上没有,自己写的
Status GetElem_Sq(SqList L, int i, ElemType &e){
//获取顺序表L中第i个位置的元素e
//i的合法值为1<=i<=ListLength_Sq(L)
if(i<1 || i>ListLength_Sq(L)) return ERROR;
e = L.elem[i-1];
return OK;
}
//获取前驱元素,基本操作,书上没有,自己写的
Status PriorElem_Sq(SqList L, ElemType cur_e, ElemType &pre_e){
//获取顺序表L中元素值为cur_e的前驱元素next_e
//成功返回OK,pre_e为前驱,失败返回FALSE,pre_e为随机值
//双指针p,pre操作;p为遍历元素的指针,pre指针永远指向p指针的前一个地址,即pre_e
ElemType *pre;
for(ElemType *p = L.elem;p<=&(L.elem[L.length-1]);p++){
if(*p == cur_e){
pre_e = *pre;
return OK;
}
pre=p;
}
return FALSE;
}
//获取后继元素,基本操作,书上没有,自己写的
Status NextElem_Sq(SqList L, ElemType cur_e, ElemType &next_e){
//获取顺序表L中元素值为cur_e的后继元素next_e
//成功返回OK,next_e为后继,失败返回FALSE,next_e为随机值
//双指针p,nxt操作;p为遍历元素的指针,nxt指针永远指向p指针的后一个地址,即next_e
ElemType *nxt = L.elem+1;
for(ElemType *p = L.elem;p<&(L.elem[L.length-1]);p++,nxt++){
if(*p == cur_e){
next_e = *nxt;
return OK;
}
}
return FALSE;
}
//顺序表插入,时间复杂度为O(n)
Status ListInsert_Sq(SqList &L, int i, ElemType e){
//在顺序表L中第i个位置之前插入新的元素e
//i的合法值为1<=i<=ListLength_Sq(L)+1
if(i<1||i>ListLength_Sq(L)+1) return ERROR; //i值不合法
if(L.length >= L.listsize){ //当前存储空间已满,增加分配
ElemType *newbase = (ElemType*)realloc(L.elem, (L.listsize+LISTINCREMENT)*sizeof(ElemType));
if(!newbase) exit(OVERFLOW); //存储分配失败
L.elem = newbase; //新基址
L.listsize += LISTINCREMENT; //增加存储容量
}
ElemType *q = &(L.elem[i-1]); //q为插入位置
//插入位置及之后的元素右移
for(ElemType *p = &(L.elem[L.length-1]);p>=q;--p)
*(p+1) = *p;
*q = e; //插入e
++L.length; //表长增1
return OK;
}
//顺序表删除,时间复杂度为O(n)
Status ListDelete_Sq(SqList &L, int i, ElemType &e){
//在顺序表L中删除第i个元素,并用e返回其值
//i的合法值为1<=i<=ListLength_Sq(L)
if(i<1 || i>ListLength_Sq(L)) return ERROR; //i值不合法
ElemType *p = &(L.elem[i-1]); //p为被删除元素的位置
e = *p; //被删除元素的值赋给e
ElemType *q = L.elem + L.length - 1; //表尾元素的位置
for(++p;p<=q;++p) *(p-1) = *p; //被删除元素之后的元素左移
--L.length;
return OK;
}
//顺序表的查找
int LocateElem_Sq(SqList L, ElemType e, Status(*compare)(ElemType, ElemType)){
//在顺序表L中查找第1个值与e满足compare()的元素的位序
//若找到,则返回其在L中的位序,否则返回0
//第三个参数是一个函数指针,该函数的必须符合以下2点要求:
//1.返回值为Status。2.有两个参数,且类型为ElemType
int i = 1; //位序i的初值为1
ElemType *p = L.elem; //p的初值为第一个元素的存储位置
//遍历顺序表
while(i <= L.length && !(*compare)(*p++ ,e)) ++i;
if(i <= L.length) return i;
else return 0;
}
//顺序表的合并,时间复杂度为O(La.length+Lb.length)
void MergeList_Sq(SqList La, SqList Lb, SqList &Lc){
//已知顺序表La和Lb的元素按值非递减排列(递增排列)
//归并La和Lb得到新的顺序表Lc,Lc的元素也按值非递减排列(递增排列)
//pa和pb指针是遍历La和Lb每一个元素的指针,pc指针永远指向Lc的待插入元素位置
ElemType *pa = La.elem,*pb = Lb.elem;
Lc.listsize = Lc.length = La.length + Lb.length;
ElemType *pc = Lc.elem = (ElemType*)malloc(Lc.listsize*sizeof(ElemType));
if(!Lc.elem) exit(OVERFLOW); //存储分配失败
//pa_last和pb_last指针是指向La和Lb最后一个元素的指针,pa<=pa_last即遍历La中每一个元素,Lb同理
ElemType* pa_last = La.elem + La.length - 1;
ElemType* pb_last = Lb.elem + Lb.length - 1;
while(pa <= pa_last && pb <= pb_last){ //归并
/**
* 判断pa和pb所指向的元素谁大,取其中较小的数添加到Lc中,然后两个指针后移
* *pc++ =*pa++;相当于以下三条语句:
* *pc = *pa; //将pa所指向的元素值赋值给pc所指向的元素值
* pc++;pa++; //pc和pa指针后移
**/
if(*pa <= *pb) *pc++ =*pa++;
else *pc++ = *pb++;
}
//以下两个while只会进入一个,因为上个while遍历的结束条件就是La或Lb遍历完毕
while(pa <= pa_last) *pc++ = *pa++; //插入La的剩余元素
while(pb <= pb_last) *pc++ = *pb++; //插入Lb的剩余元素
}
//顺序表的输出
void Display_Sq(SqList L){
printf("马上就输出这个叫L的线性表啦~\n");
printf("顺序表的内容:");
for(int i=0;i<ListLength_Sq(L);i++){
if(i!=0) printf(" ");
printf("%d",L.elem[i]);
}
printf("\n");
}
Status cmp(ElemType a,ElemType b){
if(a>b) return OK;
else return FALSE;
}
int main(){
SqList L;
InitList_Sq(L); //初始化线性表
int a[5] = {4,2,1,3,5};
for(int i=0;i<5;i++){ //插入元素到线性表L
ListInsert_Sq(L,i+1,a[i]);
}
Display_Sq(L); //输出线性表
printf("线性表为空?%s\n\n",
ListEmpty_Sq(L)==TRUE?"TRUE":"FALSE");//判断线性表是否为空
printf("顺序表的长度:%d\n\n",
ListLength_Sq(L)); //输出线性表长度
int tmp; //临时变量,方便下面方法使用
GetElem_Sq(L,2,tmp); //获取指定元素
printf("第2个元素是:%d\n\n",tmp);
PriorElem_Sq(L,5,tmp); //获取前驱
printf("5的前驱元素为:%d\n\n",tmp);
NextElem_Sq(L,2,tmp); //获取后继
printf("2的后继元素为:%d\n\n",tmp);
ListDelete_Sq(L,3,tmp); //删除元素
printf("删除第3个元素后:\n");
Display_Sq(L);
tmp = LocateElem_Sq(L,3,cmp); //查找第1个值与e满足cmp的元素的位序
printf("\n第一个比3小的元素下标为:%d\n\n",tmp);
printf("清空线性表咯~\n"); //清空线性表
ClearList_Sq(L);
Display_Sq(L);
DestoryList_Sq(L); //删除线性表
return 0;
}
三、运行截图

《数据结构(C语言版)》严蔚敏代码实现———顺序表的更多相关文章
- 数据结构(C语言版)严蔚敏->排序
@ 目录 1. 插入排序 1.1 直接插入排序 1.2 折半插入排序 1.3 希尔排序(Shell Sort) 2.交换排序 2.1 冒泡排序 2.2 快速排序 3. 选择排序 3.1 简单选择排序 ...
- 深入浅出数据结构C语言版(7)——特殊的表:队列与栈
从深入浅出数据结构(4)到(6),我们分别讨论了什么是表.什么是链表.为什么用链表以及如何用数组模拟链表(游标数组),而现在,我们要进入到对线性表(特意加了"线性"二字是因为存在多 ...
- 《数据结构-C语言版》(严蔚敏,吴伟民版)课本源码+习题集解析使用说明
<数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明 先附上文档归类目录: 课本源码合辑 链接☛☛☛ <数据结构>课本源码合辑 习题集全解析 链接☛☛☛ ...
- c++学习书籍推荐《清华大学计算机系列教材:数据结构(C++语言版)(第3版)》下载
百度云及其他网盘下载地址:点我 编辑推荐 <清华大学计算机系列教材:数据结构(C++语言版)(第3版)>习题解析涵盖验证型.拓展型.反思型.实践型和研究型习题,总计290余道大题.525道 ...
- 数据结构C语言版 有向图的十字链表存储表示和实现
/*1wangxiaobo@163.com 数据结构C语言版 有向图的十字链表存储表示和实现 P165 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h> ...
- 数据结构C语言版 表插入排序 静态表
数据结构C语言版 表插入排序.txt两个人吵架,先说对不起的人,并不是认输了,并不是原谅了.他只是比对方更珍惜这份感情./* 数据结构C语言版 表插入排序 算法10.3 P267-P270 编译 ...
- 数据结构C语言版 弗洛伊德算法实现
/* 数据结构C语言版 弗洛伊德算法 P191 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h>#include <limits.h> # ...
- 【数据结构(C语言版)系列二】 栈
栈和队列是两种重要的线性结构.从数据结构角度看,栈和队列也是线性表,但它们是操作受限的线性表,因此,可称为限定性的数据结构.但从数据类型角度看,它们是和线性表大不相同的两类重要的抽象数据类型. 栈的定 ...
- 【数据结构(C语言版)系列三】 队列
队列的定义 队列是一种先进先出的线性表,它只允许在表的一端进行插入,而在另一端删除元素.这和我们日常生活中的排队是一致的,最早进入队列的元素最早离开.在队列中,允许插入的一端叫做队尾(rear),允许 ...
- 【数据结构(C语言版)系列一】 线性表
最近开始看数据结构,该系列笔记简单记录总结下所学的知识,更详细的推荐博主StrayedKing的数据结构系列,笔记部分也摘抄了博主总结的比较好的内容. 一些基本概念和术语 数据是对客观事物的符号表示, ...
随机推荐
- java循环结构中局部变量和成员变量
前言 在前两篇文章中,壹哥给大家讲解了Java里的条件分支,包括if和switch两种情况.我们知道,除了条件分支结构,还有循环结构,所以接下来的一个学习重点就是Java里的循环.但在学习循环之前,我 ...
- IO 流分类
更多内容,前往 IT-BLOG 一.File File 类(磁盘操作)可以用于表示文件和目录的信息,但是它不表示文件的内容.递归地列出一个目录下所有文件: 1 public static void l ...
- CSAPP-Attack Lab
目录 Code Injection Attacks Level 1 Level 2 Level_3 Return-Oriented Programming Level_4 Level_5 获取栈顶地址 ...
- DFS总结
常见剪枝方法 优化搜索顺序 优先搜索决策树较小的点,例如在165. 小猫爬山一题中,优先搜索体重较大的扩展出的情况较少 排除冗余信息 如果某些情况在此前已经被搜索过了,那么无需继续搜索 可行性剪枝 如 ...
- java创建线程的方式有几种?
java中创建线程的方式有多少种,这个问题也是众多纷纭,这个时候更应该参考官方文档(https://docs.oracle.com/javase/8/docs/api/java/lang/Thread ...
- 从pcap文件中提取pcma音频
操作系统 :Windows10_x64 .CentOS 7.6.1810_x64 wireshark版本:3.6.12 Python 版本 : 3.9.12 一.背景描述 工作中有时候会遇到需要从 ...
- 容器云平台监控告警体系(三)—— 使用Prometheus Operator部署并管理Prometheus Server
1.概述 Prometheus Operator是一种基于Kubernetes的应用程序,用于管理Prometheus实例和相关的监控组件.它是由CoreOS开发的开源工具,旨在简化Prometheu ...
- 分享一个修改了xml文件再也不用重启的项目mybatis-xmlreload
自我18年使用 Mybaits 以来,开发环境中如果修改了 xml 文件后,只有重启项目才能生效,如果小项目重启还好,但是对于一个重启需要十几分钟的大型项目来说,这就非常耗时了.开发人员因为修改了xm ...
- pandas之iteration遍历
遍历是众多编程语言中必备的一种操作,比如 Python 语言通过 for 循环来遍历列表结构.那么 Pandas 是如何遍历 Series 和 DataFrame 结构呢?我们应该明确,它们的数据结构 ...
- 补五月三号java基础知识
1.泛型技术可以通过一种类型或方法操纵各种不同类型的对象,同时又提供了编译时的类型安全保证.2.容器(即集合)是以类库形式 提供的多种数据结构,用户在编程时可直接使用3.泛型其实质就是将数据的类型参数 ...