存储结构
顺序存储结构:逻辑上连续,物理存储上也连续
链式存储结构:逻辑上连续,物理存储上不连续
顺序表–操作数据
顺序表是在计算机内存中以数组的形式保存的线性表。
顺序存储:
类似于数组,顺序表比数组多带一个元素来记录存储的元素个数count
定长顺序表
定长顺序表 —》类似于数组
不定长顺序表—》C++的STL vector
数组适用于值比较固定的情况 存储数据
数组没有成套的方法
计数法:(即顺序表的定义)
struct data
{
int num[10];
int count;
}
程序案例----
Seqlist.h
#pragma once
//定义顺序表 以数组形式存储 所以无法扩容 写判满函数
#ifndef _SEQLIST_H
#define _SEQLIST_H
#define LENGTH 10
typedef int ElemType;
typedef struct _Seqlist
{
ElemType data[LENGTH];//存储数据元素的空间 固定大小的
int count;//记录存储的数据元素个数
}Seqlist,*pSeqlist;//*pSeqlist是指针
static bool IsFull(pSeqlist seq);//判满
static bool IsEmpty(pSeqlist seq);//判空
bool InitList_Sq(pSeqlist seq);//初始化
void InsertList_SqOfHead(pSeqlist seq, ElemType val);//插入元素 头插 以及插入的元素
void InsertList_SqOfTail(pSeqlist seq, ElemType val);//插入元素 尾插 以及插入的元素
void InsertList_SqOfPos(pSeqlist seq, ElemType val,int pos);//插入元素 指定位置插入
void ShowList_Sq(pSeqlist seq);
void DeleteList_SqOfHead(pSeqlist seq);//头删
void DeleteList_SqOfTail(pSeqlist seq);//尾删
void DeleteList_SqOfPos(pSeqlist seq,int pos);//指定位置删除
bool FindList_SqOfPos(pSeqlist seq, int pos, ElemType &val);//根据位置返回元素的值
int FindList_SqOfVal(pSeqlist seq, ElemType val);//根据元素的值返回位置
int FindList_SqOfLocate(pSeqlist seq, ElemType val,
bool(*compare)(ElemType,ElemType));//根据函数条件compare和val值查找元素---函数指针
void ReverseList_Sq(pSeqlist seq, void(*Swap)(ElemType&, ElemType&));//逆置顺序表元素
//还是传入了函数指针 因为万一交换的是结构体里的某一个怎么办
bool compare(ElemType a, ElemType b);
void Swap(ElemType &a, ElemType &b);
#endif
/*
typedef int ElemType;
#define LENGTH 10
typedef struct _Alterlist
{
ElemType *data;//存储数据元素的空间首地址得指针
int count;//记录已存储的数据元素个数
int listsize;//记录存储空间元素总大小
}Alterlist, *pAlterlist;//*pAlterlist是指针
bool InitList_Sq(pAlterlist alist)
{
assert(alist != NULL);//断言指针是否为空 只在debug版本下有效
if (alist == NULL)
{
return false;//保证release版本也能判断
}
alist->data = (ElemType *)malloc(sizeof(ElemType)*LENGTH);
}
*/
Seqlist.cpp
// Seqlist.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include"assert.h"
#include"Seqlist.h"
#include<string.h>
#include <iostream>
using namespace std;
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门提示:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
//判断是否满 写成静态函数是因为静态函数将函数符号生成为LOCAL 只能在本文件中访问 外部不能访问
static bool IsFull(pSeqlist seq)
{
if (seq->count == LENGTH)
{
return true;
}
return false;
}
static bool IsEmpty(pSeqlist seq)//判空
{
if (seq->count == 0)
{
return true;
}
return false;
}
bool compare(ElemType a , ElemType b)
{
if ( a == b)
{
return true;
}
return false;
}
void Swap(ElemType &a, ElemType &b)
{
ElemType c = a;
a = b;
b = c;
}
bool InitList_Sq(pSeqlist seq)
{
assert(seq != NULL);//断言指针是否为空 只在debug版本下有效
if (seq == NULL)
{
return false;//保证release版本也能判断
}
seq->count = 0;
seq->data[30];
}
void InsertList_SqOfHead(pSeqlist seq, ElemType val)
{
if (IsFull(seq))
{
cout << "内存已满!" << endl;
return;
}
//移动已有的数据
for (int i = seq->count; i > 0; i--)
{
seq->data[i] = seq->data[i - 1];
}
seq->data[0] = val;
seq->count++;
}
void InsertList_SqOfTail(pSeqlist seq, ElemType val)
{
if (IsFull(seq))
{
cout << "内存已满!" << endl;
return;
}
seq->data[seq->count++] = val;//直接在尾部进行插入数据
}
void InsertList_SqOfPos(pSeqlist seq, ElemType val, int pos)
{
if (IsFull(seq))
{
cout << "内存已满!" << endl;
return;
}
//判断pos位置是否合法
if (pos<0 || pos>seq->count)//pos=count相当于尾插 因为是数组
{
return;
}
if (pos > seq->count)
pos = seq->count;
//在pos位置插入和头插一个思想 同样是移动数据 只不过是在pos位置后进行移动
for (int i = seq->count; i > pos; i--)
{
seq->data[i] = seq->data[i - 1];
}
seq->data[pos] = val;
seq->count++;
}
void ShowList_Sq(pSeqlist seq)
{
for (int i = 0; i < seq->count; ++i)
{
printf("%d", seq->data[i]);
}
printf("\n");
}
void DeleteList_SqOfHead(pSeqlist seq)
{
if (IsEmpty(seq))
{
return;
}
for (int i = 0; i <seq->count-1; i++)
{
seq->data[i] = seq->data[i + 1];
}
seq->count--;
}
void DeleteList_SqOfTail(pSeqlist seq)
{
if (IsEmpty(seq))
{
return;
}
seq->count--;
}
void DeleteList_SqOfPos(pSeqlist seq, int pos)
{
if (IsEmpty(seq))
{
return;
}
if (pos<0 || pos>=seq->count)//pos=count相当于要删除一个不存值的 因为是数组
{
return;
}
if (pos > seq->count)
pos = seq->count;
for (int i = pos; i < seq->count-1; i++)
{
seq->data[i] = seq->data[i + 1];
}
seq->count--;
}
bool FindList_SqOfPos(pSeqlist seq, int pos, ElemType &val)
{
if (pos < 0 || pos >= seq->count)//pos=count相当于要删除一个不存值的 因为是数组
{
return false;
}
val = seq->data[pos];
return true;
}
int FindList_SqOfVal(pSeqlist seq, ElemType val)
{
for (int i = 0; i < seq->count; i++)
{
if (seq->data[i] == val)
{
return i;
}
}
return -1;
}
//如果ElemType val是个结构体 用上面方法就不行了 不能进行直接比较 就得用下面这个
int FindList_SqOfLocate(pSeqlist seq, ElemType val, bool(*compare)(ElemType, ElemType))
{
for (int i = 0; i < seq->count; ++i)
{
if (compare(val, seq->data[i]))//使用我传的函数来进行判断
{
return i;
}
}
return false;
}
void ReverseList_Sq(pSeqlist seq,void(*Swap)(ElemType&,ElemType&))//逆置
{
int i = 0;
int j = seq->count - 1;
for (; i < j; ++i, --j)
{
swap(seq->data[i], seq->data[j]);
}
}
main.cpp
#include "pch.h"
#include"Seqlist.h"
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
int main()
{
/*-------------------------- -定长顺序表-----------------------------------------------------*/
/* Seqlist seq;//栈区定义的顺序表 是由系统管理的 程序员只管堆区的数据(malloc)
InitList_Sq(&seq);
InsertList_SqOfHead(&seq, 10);
InsertList_SqOfHead(&seq, 20);
InsertList_SqOfHead(&seq, 30);
ShowList_Sq(&seq);//302010
InsertList_SqOfTail(&seq, 40);
ShowList_Sq(&seq);//30201040
InsertList_SqOfPos(&seq, 40,2);//3020401040
ShowList_Sq(&seq);
DeleteList_SqOfHead(&seq);//20401040
ShowList_Sq(&seq);
DeleteList_SqOfTail(&seq);//204010
ShowList_Sq(&seq);
int val = 0;
FindList_SqOfPos(&seq, 1, val);
cout << val << endl;
int i = FindList_SqOfVal(&seq, 10);
cout << "i: " << i << endl;
int j = FindList_SqOfLocate(&seq, 40, compare);
cout <<"j: "<< j << endl;
ReverseList_Sq(&seq, Swap);//逆置
ShowList_Sq(&seq);
*/
}
不定长顺序表
不定长顺序表与定长顺序表基本相似,都是在计算机内存中以数组的形式保存的线性表,逻辑相邻,地址也相邻,可以通过下标任意访问。区别是不定长顺序表可扩容(动态开辟)。
结构如何构造:
数据存放在数组中,需要一个变量记录有效个数(即存放了数据的个数),需要扩容那么就要知道当前内存是否为满,设置一个变量记录总长度。所以结构体设计为下图:
main.cpp
#include "pch.h"
#include"Alterlist.h"
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
int main()
{
_AlterList seq;//栈区定义的顺序表 是由系统管理的 程序员只管堆区的数据(malloc)
InitList_AL(&seq);
Insert_ALHead(&seq, 10);
Insert_ALHead(&seq, 20);
Insert_ALHead(&seq, 30);
ShowALList_Sq(&seq);//302010
Delete_AL(&seq);//20401040
Insert_ALHead(&seq, 40);
Insert_ALHead(&seq, 50);
Insert_ALHead(&seq, 60);
Insert_ALHead(&seq, 70);
Insert_ALHead(&seq, 80);
ShowALList_Sq(&seq);
}
AlterList.cpp
#include "pch.h"
#include "AlterList.h"
#include <assert.h>
#include <string.h>
#include <malloc.h>
#include<iostream>
using namespace std;
//*********************************
// 判空函数
bool IsEmpty(pAlterList alist)
{
if (alist->count == 0)
return true;
return false;
}
// 判满函数
bool IsFull(pAlterList alist)
{
if (alist->count == alist->listsize)
return true;
return false;
}
//*********************************
bool InitList_AL(pAlterList alist)
{
assert(alist != NULL);//assert只在DEBUG版本有效,若编译成release版本则被忽略
if (alist == NULL)
{
return false;
}
alist->data = (ElemType *)malloc(sizeof(ElemType) * LENGTH);
assert(alist->data != NULL);
if (alist->data == NULL)
{
return false;
}
alist->count = 0;
alist->listsize = LENGTH;
return true;
}
// 扩容函数
void resize1(pAlterList alist)//用realloc进行扩容
{
alist->data = (ElemType *)realloc(alist->data, sizeof(ElemType)*(alist->listsize + LENGTH));
assert(alist->data != NULL);//如果这个内存可以扩容
alist->listsize += LENGTH;//更新当前顺序表的长度
}
void resize2(pAlterList alist)//申请一个更大空间,将旧数据拷贝,释放旧空间
{
ElemType *tmp = (ElemType *)malloc(sizeof(ElemType)*(alist->listsize + LENGTH));
for (int i = 0; i < alist->count; ++i)
{
tmp[i] = alist->data[i];
}
delete[]alist->data;//删掉原先指针指向的内存
alist->data = tmp;//将原先指针指向新开辟的内存
alist->listsize += LENGTH;
}
void Insert_ALHead(pAlterList alist, ElemType val)
{
if (IsFull(alist))
{
cout << "内存已满!" << endl;
return;
}
//移动已有的数据
for (int i = alist->count; i > 0; i--)
{
alist->data[i] = alist->data[i - 1];
}
alist->data[0] = val;
alist->count++;
}
void Delete_AL(pAlterList alist)
{
if (IsEmpty(alist))
{
return;
}
for (int i = 0; i < alist->count - 1; i++)
{
alist->data[i] = alist->data[i + 1];
}
alist->count--;
}
void ShowALList_Sq(pAlterList alist)
{
for (int i = 0; i < alist->count; ++i)
{
printf("%d", alist->data[i]);
}
printf("\n");
}
AlterList.h
#pragma once
#pragma once
typedef int ElemType;
#define LENGTH 6
typedef struct _AlterList
{
ElemType *data; // 指向存储数据元素的空间首地址的指针
int count; // 记录已存储的数据元素的个数
int listsize; // 记录存储空间元素总大小
}AlterList, *pAlterList;
//初始化函数
bool InitList_AL(pAlterList alist);
//判空
bool IsEmpty(pAlterList alist);
//判满
bool IsFull(pAlterList alist);
//扩容1
void resize1(pAlterList alist);
//扩容2
void resize2(pAlterList alist);
// 插入元素的函数
void Insert_ALHead(pAlterList alist,ElemType val);
// 删除函数
void Delete_AL(pAlterList alist);
// 查找
//void Select_AL(pAlterList alist, ElemType val);
// 元素逆置
//void Insert_AL(pAlterList alist, ElemType val);
// 清空元素
// 销毁顺序表
// 显示元素
void ShowALList_Sq(pAlterList alist);