顺序表
前言
顺序表是在计算机内存中以数组的形式保存的线性表,是指使用一组连续分配存储单元有序的存储数据元素的线性结构。
顺序表还有后面讲的单链表、循环链表、双链表都是链表,根本区别是在内存中存储数据的方式不同,每种方式都有优劣点,这也根据应用场景的不同,决定用什么方式存储数据。
基本算法
在线性表中算法操作中,异常判断很重要,包括链表是否为空,插入位置是否正确等等。
- 插入数据元素
在顺序表中第n个位置插入新的元素e。
STATU insertElem(SqList *pList, int pos, ElemType elem) { int i = 0; // 判断要插入的位置是否合理 if (pos < 0 || pos > pList->length) return ERROR; // 关键算法:将data[pos]及后面的元素都向后移动一个位置 for (i = pList->length - 1; i > pos; i--) { pList->data[i] = pList->data[i-1]; } pList->data[pos] = elem; pList->length++; // 顺序表长度加1 return OK; }
同理删除元素也是这样的操作。
插入操作:
1. 如果插入位置不合理,抛出异常
2. 如果超过容量,跑出异常或者动态增加容量。
3. 如果从最后一个元素开始向前遍历到第i元素位置,其后面元素都向后移动一个位置。
4. 将元素插入在位置i处
5. 表长加1.
6. 删除工作和插入很相似。关键是前面的异常判断。
在上面顺序表的插入和删除操作中,最快的就是在表尾插入,为时间复杂度为1,最坏的情况是在表头插入,时间复杂度为n-1,所以插入和删除的时间复杂度为O(n),平均复杂度为:O((n-1)/2))
优点 | 缺点 |
---|---|
无须为表中逻辑关系增加额外的存储空间 | 插入和删除需要移动大量元素 |
可以快速存取表中任意位置元素 | 当线性表长度变化较大时,难以确定存储空间的容量 |
造成存储空间的“碎片”,释放内存时 |
顺序表代码实现
以c语言实现顺序表的基本操作
序号 | 函数名称 | 函数说明 |
---|---|---|
1 | InitList | 创建一个为空的顺序表 |
2 | CreateList | 根据数组elems构建一个顺序表 |
3 | InsertElem | 在顺序表中第pos位置插入元素elem |
4 | DeleteElem | 在顺序表中第pos位置删除元素elem |
5 | GetElem | 获取在位置为Pos位置元素,并返回pelem |
6 | GetElemLocation | 获取元素elem在顺序表中第一次出现的位置,如果不存在返回-1 |
7 | PrintList | 输出整个顺序表 |
#include "stdafx.h" #include <stdio.h> #include <stdlib.h> /*********************************************************************************************************************** 第一部分,数据结构、宏定义 ***********************************************************************************************************************/ #define MAXSIZE 10 typedef enum { // 状态码 OK = 0, ERROR = 1 } STATU; typedef enum { // C语言中没有bool型,为方便,自定义一个BOOL型 TRUE = 0, FALSE = -1 } BOOL; typedef int ElemType; // 元素类型 typedef struct { // 顺序表的结构类型 ElemType data[MAXSIZE]; int length; } SqList; /*********************************************************************************************************************** 第二部分,函数实现 ***********************************************************************************************************************/ /******************************************************************************* Funtion : initList Description : 初始化一个空的顺序表 *******************************************************************************/ void initList(SqList *pList) { pList->length = 0; } /******************************************************************************* Funtion : createList Description : 根据数组 elems 构建一个顺序表 *************************************************/ STATU createList(SqList *pList, ElemType elems[], int size) { int i = 0; // 判断数组大小是否超过最大限制 if (size > MAXSIZE) return ERROR; for (i = 0; i < size; i++) { pList->data[i] = elems[i]; } pList->length = size; return OK; } /******************************************************************************* Funtion : insertElem Description : 在顺序表中第 pos 个位置插入元素 elem *******************************************************************************/ STATU insertElem(SqList *pList, int pos, ElemType elem) { int i = 0; // 判断要插入的位置是否合理 if (pos < 0 || pos > pList->length) return ERROR; // 将data[pos]及后面的元素都向后移动一个位置 for (i = pList->length - 1; i > pos; i--) { pList->data[i] = pList->data[i-1]; } pList->data[pos] = elem; pList->length++; // 顺序表长度加1 return OK; } /******************************************************************************* Funtion : removeElem Description : 在顺序表中移除第 pos 个元素,并由 pElem 返回其值 *******************************************************************************/ STATU removeElem(SqList *pList, int pos, ElemType *pElem) { int i = 0; // 判断要删除的位置是否合理 if (pos < 0 || pos > pList->length) return ERROR; *pElem = pList->data[pos]; // 将data[pos]后面的元素都向前移动一个位置 for (i = pos; i < pList->length; i++) { pList->data[i] = pList->data[i+1]; } pList->length--; // 顺序表长度减1 return OK; } /******************************************************************************* Funtion : getElem Description : 获取顺序表上位置为 pos 的元素,并由 pElem 返回其值 *******************************************************************************/ STATU getElem(SqList list, int pos, ElemType *pElem) { // 判断位置是否合理 if (pos < 0 || pos > list.length - 1) return ERROR; *pElem = list.data[pos]; return OK; } /******************************************************************************* Funtion : locateElem Description : 获取元素 elem 在顺序表上第一次出现的位置,如果不存在返回 -1 *******************************************************************************/ int locateElem(SqList list, ElemType elem) { int pos = 0; for (pos = 0; pos < list.length; pos++) { if (elem == list.data[pos]) return pos; } return -1; } /******************************************************************************* Funtion : printList Description : 打印整个顺序表 *******************************************************************************/ void printList(SqList list) { int i = 0; if (0 == list.length) { printf("SqList is empty\n"); return; } printf("SqList:"); for (i = 0; i < list.length; i++) { printf(" %d", list.data[i]); } printf("\n"); }
综述
顺序的创建的初始化就是相当于对数组的初始化,获取元素和位置,也和数组相同,关键是在删除和插入的时需要元素进行移动。在插入操作时,不能超过最大长度,如果超过需要扩容。
后面讲详细讲解线性表和链表的应用场景
版权声明:本文为博主原创文章,未经博主允许不得转载。