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
}
相关推荐
xier_ran1 天前
【C++】“内部”、“外部”、“派生类”、“友元“类
java·开发语言·c++
雨墨✘1 天前
基于比较的三种排序算法:插入排序、合并排序和快排序
数据结构·算法·排序算法
熬夜敲代码的猫1 天前
C/C++:内存管理
c语言·c++·动态内存管理
im_AMBER1 天前
从面试题看JS变量提升
开发语言·前端·javascript·前端框架
故事和你911 天前
洛谷-数据结构1-2-二叉树1
开发语言·数据结构·c++·算法·leetcode·动态规划·图论
大橘1 天前
【qml-5.1】qml与c++交互(QML_ELEMENT/QML_SINGLETON)
开发语言·c++·qt·交互·qml
凭君语未可1 天前
从静态代理走向动态代理:理解 JDK 动态代理的本质
java·开发语言
小碗羊肉1 天前
【从零开始学Java | 第三十八篇】序列化流(Object Stream)
java·开发语言
百锦再1 天前
使用JavaScript获取和解析页面内容的完整指南
开发语言·前端·javascript·python·flask·fastapi
iCxhust1 天前
C#如何实现textbox文本多行输出 且自动换行输出
开发语言·c#