线性表之顺序表(一)
来源:互联网 发布:easycharts 数据小偷 编辑:程序博客网 时间:2024/06/10 18:45
在这里我们将介绍线性表的顺序存储结构–顺序表。这里我们介绍两种类型的顺序表,一种是静态的顺序表,另一种是动态增长的顺序表;并使用C和C++两种语言进行描述。这里给出C语言实现的具体的代码和说明,而C++的实现只是简单贴代码,不再详细说明。
一、相关概念
1.顺序表的概念
线性表的顺序存储结构称为顺序表(sequential list).
2.特点
(1)顺序表是用一段地址连续的存储单元一次存储线性表的数据元素;(2)相邻元素不仅逻辑上相邻,而且在物理内存上也是相邻的;(3)顺序表的元素可以随机存取(访问)(4)插入和删除比较麻烦,需要大量移动元素
二、静态顺序表
1.结构体定义(C语言描述)
顺序表和数组本质上一样的,只不过比数组多了一个记录有效元素个数的变量,其他特点基本都一样,比如说随机访问等。
#define SIZE 10 //静态顺序表最大的元素个数上限typedef struct Seqlist{ int iElem_a[SIZE]; //顺序表总空间 int iLength_st;//表中有效元素个数}Seqlist;
2.顺序表操作
我们将顺序表操作的函数的声明写在Seqlist.h文件中:
#ifndef SEQLIST_H_ //防止头文件被重复包含#define SEQLIST_H_#define SIZE 10typedef struct Sqlist{ int iElem_a[SIZE]; int iLength_st;}Sqlist;void InitSeqlist(Sqlist *pList); //顺序表初始化bool Insert(Sqlist *pList, int iPos, int iVal);//插入bool DeleteByPos(Sqlist *pList, int iPos);//删除void Destroy(Sqlist *pList);//销毁顺序表,在静态顺序表中没实质性作用void Clear(Sqlist *pList);//清空顺序表bool IsEmpty(Sqlist *pList);//顺序表为空返回truebool IsFull(Sqlist *pList);//顺序表满返回trueint GetLength(Sqlist *pList);//获取顺序表有效元素个数bool GetValByPos(Sqlist *pList, int iPos, int *iRetVal);//获取指定位置元素void PrintSqlist(Sqlist *pList);//输出顺序表#endif
下面在Seqlist.c文件中给出顺序表操作的具体实现:
#include <stdio.h>#include <stdlib.h>#include "Seqlist.h"int main(void){ Sqlist list; InitSeqlist(&list); for (int i = 0; i < 12; ++i) { Insert(&list, 0, i); } PrintSqlist(&list); Insert(&list, 10, 10); PrintSqlist(&list); /*for (int i = 0; i < 12; ++i) { DeleteByPos(&list, 0); PrintSqlist(&list); } PrintSqlist(&list);*/ for (int i = 0; i < 12; ++i) { int iRt; GetValByPos(&list, i, &iRt); printf("%5d\n", iRt); } printf("\n"); return 0;}//初始化顺序表,注意异常情况检查void InitSeqlist(Sqlist *pList){ if (NULL == pList) //确保链表存在 { printf("The Seqlist isn't exist!!!\n"); return; } pList->iLength_st = 0;}//插入元素,先判断是否顺序表已满,然后再判断插入位置是否正确,移动元素插入bool Insert(Sqlist *pList, int iPos, int iVal){ //顺序表存在而且没有满 if (pList == NULL) { printf("The Sqlist isn't exist!!!\n"); return false; } if (IsFull(pList)) { printf("The Sqlist is full!\n"); return false; } //插入位置是否合法 if (iPos > pList->iLength_st || iPos < 0) { printf("The Insert positon is valid.\n"); return false; } //移动元素 for (int iIndex = pList->iLength_st - 1; iIndex >= iPos; --iIndex) { pList->iElem_a[iIndex + 1] = pList->iElem_a[iIndex]; } //放入 pList->iElem_a[iPos] = iVal; pList->iLength_st += 1; return true;}//删除指定位置的元素,找到删除的元素的位置后,直接移动元素进行覆盖,记得改变顺序表有效元素的个数bool DeleteByPos(Sqlist *pList, int iPos){ if (NULL == pList) { printf("The seqlist isn't exist!!!\n"); return false; } if (IsEmpty(pList)) { //printf("The seqlist is empty!!!\n"); return false; } if (iPos < 0 || iPos > pList->iLength_st - 1) { printf("The insert position is valid!!!\n"); return false; } for (int iIndex = iPos; iIndex < pList->iLength_st - 1; ++iIndex) { pList->iElem_a[iIndex] = pList->iElem_a[iIndex + 1]; } --pList->iLength_st; return true;}//销毁顺序表,因为这里是静态顺序表,所以这个函数没有实质性的作用void Destroy(Sqlist *pList){ Clear(pList);}//清空顺序表,直接将记录顺序表有效元素个数的变量置为0void Clear(Sqlist *pList){ if (NULL == pList) { printf("The seqlist isn't exist\n"); return; } pList->iLength_st = 0;}//判断顺序表是否为空bool IsEmpty(Sqlist *pList){ if (NULL == pList) { printf("The Seqlist isn't exist!!!\n"); return false; } return 0 == pList->iLength_st;}//判断顺序表是否已满bool IsFull(Sqlist *pList){ if (NULL == pList) { printf("The Seqlist isn't exist!!!\n"); return false; } return SIZE == pList->iLength_st;}//获取顺序表有效元素的个数int GetLength(Sqlist *pList){ if (NULL == pList) { printf("The seqlist isn't exist.\n"); return -1; } return pList->iLength_st;}//获取顺序表中iPos位置元素的值bool GetValByPos(Sqlist *pList, int iPos, int *iRetVal){ if (NULL == pList) { printf("The seqlist isn't exist.\n"); return false; } if (iPos < 0 || iPos >= pList->iLength_st) { printf("The position is valid\n"); return false; } *iRetVal = pList->iElem_a[iPos]; return true;}//打印顺序表中的元素void PrintSqlist(Sqlist *pList){ if (NULL == pList || pList->iLength_st == 0) { return; } for (int iCount = 0; iCount < pList->iLength_st; ++iCount) { printf("%5d", pList->iElem_a[iCount]); } printf("\n");}
三、动态顺序表
动态顺序表和静态顺序表的区别在于动态顺序表可以动态进行增长,而静态顺序表的最大容量是在程序运行前已经写好的,无法改变。
1.结构体定义(C语言描述)
#define INIT_SIZE 10 //初始化顺序表大小#define INC_SIZE 10 //顺序表的分配增量typedef struct DSqlist{ int *iElem_st; //存储空间基址 int iLength_st; //当前长度 int iSize_st; //当前分配的存储容量}DSqlist;
2.动态顺序表操作
动态增长的顺序表和静态顺序表的操作大部分相同,主要不同在于两个地方。一个是当顺序表满时,动态顺序表可以再增长从而插入元素,而静态顺序表则无法再插入元素;二是在销毁顺序表时两者不一样。我们将顺序表操作的函数的声明写在DynamicSeqlist.h文件中:
#ifndef DYNAMICSEQLIST_H_#define DYNAMICSEQLIST_H_#define INIT_SIZE 10 //初始化顺序表大小#define INC_SIZE 10 //顺序表的分配增量typedef struct DSqlist{ int *iElem_st; //存储空间基址 int iLength_st; //当前长度 int iSize_st; //当前分配的存储容量}DSqlist;bool IsExist(DSqlist *pList); //判断顺序表是否存在void InitDSeqlist(DSqlist *pList); //初始化bool Insert(DSqlist *pList, int iPos, int iVal);//插入bool DeleteByPos(DSqlist *pList, int iPos); //删除void Destroy(DSqlist *pList); //销毁void Clear(DSqlist *pList); //清空bool IsEmpty(DSqlist *pList); //判断是否为空bool IsFull(DSqlist *pList); //判断是否为满int GetLength(DSqlist *pList); //获取有效元素个数bool GetValByPos(DSqlist *pList, int iPos, int *iRetVal); //获取指定位置元素的值void PrintSqlist(DSqlist *pList); //打印元素bool Resize(DSqlist *pList); //重新分配内存空间#endif
下面在DynamicSeqlist.c文件中给出在以上操作的具体C语言代码实现:
#include"DynamicSeqlist.h"#include <stdio.h>#include <stdlib.h>#include <string.h>int main(void){ DSqlist list; InitDSeqlist(&list); for (int i = 0; i < 15; ++i) { Insert(&list, 0, i); } PrintSqlist(&list); printf("%5d\n", list.iSize_st); for (int i = 0; i < 15; ++i) { DeleteByPos(&list, 0); PrintSqlist(&list); } PrintSqlist(&list); return 0;}bool IsExist(DSqlist *pList){ return pList != NULL;}void InitDSeqlist(DSqlist *pList){ if (!IsExist(pList)) { printf("The dynamic seqlist isn't exist.\n"); return; } pList->iElem_st = (int*)malloc(sizeof(int) * INIT_SIZE); if (NULL == pList->iElem_st) { printf("Alloc the memory is failed.\n"); return; } pList->iSize_st = INIT_SIZE; pList->iLength_st = 0;}bool Insert(DSqlist *pList, int iPos, int iVal){ if (!IsExist(pList)) { printf("The dynamic seqlist isn't exist.\n"); return false; } if (IsFull(pList)) { Resize(pList); } if (iPos < 0 || iPos > pList->iLength_st) { printf("The insert position is valid.\n"); return false; } for (int iIndex = pList->iLength_st - 1; iIndex >= iPos; --iIndex) { pList->iElem_st[iIndex + 1] = pList->iElem_st[iIndex]; } pList->iElem_st[iPos] = iVal; pList->iLength_st++; return true;}bool DeleteByPos(DSqlist *pList, int iPos){ if (!IsExist(pList)) { printf("The dynamic seqlist isn't exist.\n"); return false; } if (IsEmpty(pList)) { printf("The seqlist is empty.\n"); return false; } if (iPos < 0 || iPos >= pList->iLength_st) { printf("The delete position is valid.\n"); return false; } for (int iIndex = iPos; iIndex < pList->iLength_st - 1; ++iIndex) { pList->iElem_st[iIndex] = pList->iElem_st[iIndex + 1]; } pList->iLength_st--; return true;}void Destroy(DSqlist *pList){ if (!IsExist(pList)) { printf("The dynamic seqlist isn't exist.\n"); return; } free(pList->iElem_st); pList->iLength_st = 0; pList->iSize_st = 0; pList->iElem_st = NULL;}void Clear(DSqlist *pList){ if (!IsExist(pList)) { printf("The dynamic seqlist isn't exist.\n"); return; } pList->iLength_st = 0;}bool IsEmpty(DSqlist *pList){ if (!IsExist(pList)) { printf("The dynamic seqlist isn't exist.\n"); return false; } return (pList->iLength_st == 0);}bool IsFull(DSqlist *pList){ if (!IsExist(pList)) { printf("The dynamic seqlist isn't exist.\n"); return false; } return (pList->iLength_st == pList->iSize_st);}int GetLength(DSqlist *pList){ if (!IsExist(pList)) { printf("The dynamic seqlist isn't exist.\n"); return -1; } return pList->iLength_st;}bool GetValByPos(DSqlist *pList, int iPos, int *iRetVal){ if (!IsExist(pList)) { printf("The dynamic seqlist isn't exist.\n"); return false; } if (iPos < 0 || iPos >= pList->iLength_st) { printf("The posiont is valid.\n"); return false; } *iRetVal = pList->iElem_st[iPos]; return true;}void PrintSqlist(DSqlist *pList){ if (!IsExist(pList)) { printf("The dynamic seqlist isn't exist.\n"); return; } for (int iIndex = 0; iIndex < pList->iLength_st; ++iIndex) { printf("%5d", pList->iElem_st[iIndex]); } printf("\n");}bool Resize(DSqlist *pList){ if (!IsExist(pList)) { printf("The dynamic seqlist isn't exist.\n"); return false; } int *pTemp = pList->iElem_st; pList->iElem_st = (int*)malloc(sizeof(int)*(pList->iSize_st + INC_SIZE)); if (NULL != pList->iElem_st) { memcpy(pList->iElem_st, pTemp, sizeof(int) * pList->iSize_st); pList->iSize_st += INC_SIZE; free(pTemp); pTemp = NULL; return true; } else { return false; }}
下面直接给出使用C++实现顺序表的代码:
//CppSeqlist.h头文件
#pragma onceconst int SIZE = 10;class CSeqList{public: CSeqList(); ~CSeqList(); int Length(); bool Get(int i, int &iRtVal); int Locate(int x); void Insert(int i, int x); void Detele(int i); void PrintList();private: int _iData_a[SIZE]; //存放数据元素的数组 int _iLength; //线性表的长度};//CppSeqlist.cpp#include "CppSeqlist.h"#include <iostream>using namespace std;CSeqList::CSeqList(){ _iLength = 0;}CSeqList::~CSeqList(){}int CSeqList::Length(){ return _iLength;}bool CSeqList::Get(int i, int &iRtVal){ if (i < 0 || i > _iLength - 1) { cout << "the position is valid.\n" << endl; return false; } iRtVal = _iData_a[i]; return true;}void CSeqList::Insert(int i, int x){ if (_iLength == SIZE) { cout << "The seqlist is full." << endl; return; } if (i < 0 || i > _iLength) { cout << "the position is valid." << endl; return; } for (int iIndex = _iLength - 1; iIndex >= i; --iIndex) { _iData_a[iIndex + 1] = _iData_a[iIndex]; } _iData_a[i] = x; ++_iLength;}void CSeqList::Detele(int i){ if (i < 0 || i > _iLength - 1) { cout << "The position is valid." << endl; return; } for (int iIndex = i; iIndex < _iLength - 1; ++iIndex) { _iData_a[iIndex] = _iData_a[iIndex + 1]; } --_iLength;}void CSeqList::PrintList(){ for (int iIndex = 0; iIndex < _iLength; ++iIndex) { cout << _iData_a[iIndex] << " "; } cout << endl;}int main(void){ CSeqList list; for (int i = 0; i < 12; ++i) { list.Insert(0, i); } list.PrintList(); return 0;}
阅读全文
1 0
- 线性表之顺序表(一)
- 线性表(一)之线性表的顺序存储结构
- 顺序线性表(一)
- 数据结构之线性结构(顺序表)【一】
- 进击的数据结构一之线性表的顺序结构
- 线性表之顺序表示算法实现(一)
- 数据结构线性表(一)之顺序存储结构思路
- 线性表之顺序表
- 线性表之顺序表
- 线性表之顺序表
- 线性表之顺序表
- 线性表之顺序表
- 线性表之顺序表
- 线性表之顺序表
- 线性表之顺序表
- 线性表之顺序表
- 线性表之顺序表
- 线性表之顺序表
- C++之ShellExecute使用详解
- 第二十一篇:内部排序总结(附各种排序算法源码)
- Qt 5.9.1 参考手册 QtTest 第5章 写一个基准线
- JDBC的工作原理和见解
- 机器学习技法系列一
- 线性表之顺序表(一)
- chrome快速打开历史纪录及好用的截屏软件
- 信号与槽、lamda表达式
- Python--机器学习
- Spring读取xml配置文件的原理与实现
- 2017中国大学生程序设计竞赛
- intellij中springboot+mybatis @Mapper注解提示Could not autowire
- 第二十二篇:HashTable相关操作实现(附完整源码)
- 单例模式