02 数据结构(C) | 线性表——顺序表的基本操作

目录

    • [1. 线性表及其逻辑结构](#1. 线性表及其逻辑结构)
    • [2. 顺序存储结构](#2. 顺序存储结构)
      • [2.1 知识点](#2.1 知识点)
      • [2.2 声明线性表](#2.2 声明线性表)
      • [2.3 基本运算](#2.3 基本运算)
        • [1. 建立顺序表](#1. 建立顺序表)
        • [2. 顺序表的基本运算](#2. 顺序表的基本运算)
          • [1. 初始化线性表 InitList(&L)](#1. 初始化线性表 InitList(&L))
          • [2. 销毁线性表 DestroyList(&L)](#2. 销毁线性表 DestroyList(&L))
          • [3. 判断空表 ListEmpty(L)](#3. 判断空表 ListEmpty(L))
          • [4. 求线性表长度 ListLength(L)](#4. 求线性表长度 ListLength(L))
          • [5. 输出线性表 DispList(L)](#5. 输出线性表 DispList(L))
          • [6. 按序号求线性表中元素 GetElem(L, i, &e)](#6. 按序号求线性表中元素 GetElem(L, i, &e))
          • [7. 按元素查找 LocateElem(L, e)](#7. 按元素查找 LocateElem(L, e))
          • [8. 插入数据元素 ListInsert(&L, i, e)](#8. 插入数据元素 ListInsert(&L, i, e))
          • [9. 删除数据元素 ListDelete(&L, i, &e)](#9. 删除数据元素 ListDelete(&L, i, &e))

1. 线性表及其逻辑结构

什么是线性表?

线性表是具有相同特性的数据元素的一个有限序列。该序列中所含元素的个数叫线性表的长度,用n表示,n>=0.

线性表三大特性:

  1. 有穷性:一个线性表中的元素个数是有限的。
  2. 一致性:一个线性表中的所有元素的性质相同。所有元素具有相同数据类型。
  3. 序列性:一个线性表中的所有元素之间的相对位置是线性的,即存在唯一的开始元素和终端元素,除此外,每个元素只有唯一的前驱元素和后继元素。

2. 顺序存储结构

2.1 知识点

  • 线性存储结构是把线性表中的所有元素按照其逻辑顺序依次存储到从计算机存储器中指定存储位置开始的一块连续的存储空间中。
  • 在c/c++中,借助数组类型来实现顺序表

在声明线性表的顺序存储结构类型时,定义一个data数组来存储线性表中的所有元素,再定义一个整型变量length来存储线性表的实际长度,并采用结构体类型SQList

2.2 声明线性表

c 复制代码
typedef struct {   // typedef表示自定义类型
	ElemType data[MaxSize];     //存放线性表中的元素
	int length;    // 存放线性表的长度
}SqList;   // 顺序表类型

2.3 基本运算

逻辑序号:从1开始

物理序号:即下标,从0开始

使用顺序表指针L和顺序表Q的区别:

使用 定义方式 解释 引用方式
顺序表指针L SQList *L 间接标识顺序表 L->length
顺序表Q SQList Q 直接标识顺序表 Q.length

采用顺序表指针的好处:

主要是为了方便顺序表的释放算法设计,并且在函数之间传递顺序表指针时会节省为形参分配的空间。

1. 建立顺序表
c 复制代码
void CreateList(SqList *&L, ElemType a[], int n) {   // 由a中的n个元素建立顺序表
	int i=0, k=0;  // k表示L中元素的个数,初始值为0
	L = (Sqlist *)malloc(sizeof(SqList));  // 分配存放线性表的空间
	while (i < n) {  
		L -> data[k]=a[i];  // 将元素a[i]存放到L中
		k++;
		i++;
	}
	L -> length=k;  // 设置L的长度
}

为什么*L要加&?
线性表需要回传给对应的实参,也就是说,L是输出型参数,所以在形参L的前面需要加上引用符&

2. 顺序表的基本运算
1. 初始化线性表 InitList(&L)
c 复制代码
void InitList(SqList *&L) {
	L = (SqList *)malloc(sizeof(SqList));  // 分配存放线性表的空间
	L->length = 0; // 设列表初始长度为0
}
2. 销毁线性表 DestroyList(&L)
c 复制代码
void DestroyList(SqList *&L) {
	free(L);  // 释放L所指顺序表空间
}
3. 判断空表 ListEmpty(L)
c 复制代码
bool ListEmpty(SqList *L) {
	return(L->length == 0);  // 空表则返回true,否则false
	// 或者 return L==NULL;
}
4. 求线性表长度 ListLength(L)
c 复制代码
int ListLength(SqList *L) {
	return(L->length);
}

如果声明线性表时,没有定义长度length,则可这样求:

c 复制代码
int ListLength(LinkNode *L) {  
    int length = 0;  // 初始化长度为0  
    LinkNode *p = L;  // 从头结点开始遍历,计算线性表长度  
    while (p != NULL) {  // 遍历到链表末尾,即NULL结点位置  
        length++;  // 长度加1,继续遍历下一个结点  
        p = p->next;  // 移动到下一个结点位置  
    }  
    return length;  // 返回线性表长度值  
}  
5. 输出线性表 DispList(L)
c 复制代码
void DispList(SqList *L) {
	for (int i=0; i<L->length; i++) {
		printf("%d", L->data[i]); 
	}
	printf("\n");
}
6. 按序号求线性表中元素 GetElem(L, i, &e)

如果i(1≤i≤n)正确,运用引用型参数e获取L中的第i个元素的值,并返回true,否则返回false

c 复制代码
bool GetElem(SqList *L, int i, ElemType &e) {
	if(i<1 || i>L->length) {
		return false;    //i参数错误时返回false
	}
	e = L->data[i-1];    // 取元素的值
	return true;   // 成功找到元素时返回true
}
7. 按元素查找 LocateElem(L, e)

查找第一个值为e的元素的逻辑序号,若不存在,就返回0

c 复制代码
int LocateElem(SqList *L, ElemType &e,) {
	int i=0;
	while(i<L->length && L->data[i]!=e) {
		i++;
	}
	if(i>=L->length) {
		return 0;   // 没找到返回0
	}else {
		return i+1;    // 找到后返回逻辑序号
	}
}

while循环平均执行(n+1)/2次,时间复杂度为O(n)

8. 插入数据元素 ListInsert(&L, i, e)

在顺序表L的第i个位置上插入新元素e。若i不正确,返回false;否则,将顺序表原来的第i个元素及以后的元素均向后移动一个位置,并从最后一个元素开始移动。腾出一个空位插入新元素,最后顺序表的长度加1并返回true

c 复制代码
bool ListInsert(SqList *&L, int i, ElemType e) {
	int j;
	if(i<1 || i>L->length+1 || L->length==Maxsize) {
		return false;
	}
	i--; // 将顺序表的逻辑序号转换成物理序号
	for(j=L->length; j>i; j--) {
		L->data[j]=L->data[j-1];  // 将data[i]及以后的元素后移一个位置
	}
	L->data[i]=e; // 插入元素e
	L->length++;  // 顺序表长度加1
	return true;   
}
9. 删除数据元素 ListDelete(&L, i, &e)

删除顺序表L的第i个元素,若i不正确,返回false,否则,将第i个元素以后的均向前移动一个位置,并从第i+1个元素开始移动

c 复制代码
bool ListDelete(SqList *&L, int i, ElemType &e) {
	int j;
	if (i<1 || i> L->length) {
		return false;
	}
	i--;
	e=L->data[i];
	for(j=i; j<L->length-1; j++) {
		L->data[j]=L->data[j+1];   // 将data[i]之后的元素前移1个位置
	}
	L->length--;  // 顺序表减1
	return true;  // 成功删除返回true
}
相关推荐
人间打气筒(Ada)2 小时前
如何基于 Go-kit 开发 Web 应用:从接口层到业务层再到数据层
开发语言·后端·golang
m0_488633322 小时前
Windows环境下编译运行C语言程序,合适工具与方法很关键
c语言·windows·git·开发工具·编译器
2501_924952692 小时前
代码生成器优化策略
开发语言·c++·算法
清风徐来QCQ2 小时前
八股文(1)
java·开发语言
lsx2024062 小时前
网站主机技术
开发语言
摇滚侠2 小时前
你是一名 java 程序员,总结定义数组的方式
java·开发语言·python
Book思议-2 小时前
【数据结构实战】C语言实现栈的链式存储:从初始化到销毁,手把手教你写可运行代码
数据结构·算法·链表··408
m0_488633322 小时前
C语言变量命名规则、入门自学、运算符优先级及数据结构介绍
c语言·数据结构·运算符优先级·变量命名·入门自学
左左右右左右摇晃2 小时前
数据结构——栈
数据结构·笔记