1.线性表
线性表(linear list)是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串。
线性表在逻辑上是线性结构,也就说是连续的一条直线。但在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
2.顺序表
顺序表是用一段物理地址连续的存储单元一次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删改查。
顺序表一般可以分为:使用定长数组存储(静态顺序表);使用动态开辟的数组存储(动态顺序表)。
下面看程序吧!
#include "SeqList.h"
#include <malloc.h>
#include <stdio.h>
#include <assert.h>
void SeqListInit(PSeq ps, int capacity){
ps->_array = (DataType*)malloc(sizeof(DataType)*capacity);
if (NULL == ps->_array){//必须判空
assert(0);//加断言,若申请空间失败,就会去查找原因。【assert(0)只在Debug调试下起作用,在Release下不起作用】
return;
}
ps->_capacity = capacity;
ps->_size = 0;
}
void SeqListPushBack(PSeq ps, DataType data){
//先把元素放进去
#if 0
assert(ps);
//顺序表满了CheckCapacity(ps);
ps->_array[ps->_size] = data;
ps->_size++;
#endif
SeqListInsert(ps, ps->_size, data);
}
void SeqListPopBack(PSeq ps){
#if 0
assert(ps);
//为空删不了,直接退出
if (SeqListEmpty(ps))
return;
ps->_size--;
#endif
SeqListErase(ps, ps->_size - 1);
}
void SeqListPushFront(PSeq ps, DataType data){
#if 0
assert(ps);
//将顺序表中所有的元素统一向后搬移一个位置
for (int i = ps->_size - 1; i >= 0; i--){ // i表示搬移元素的下标
//for (int i = ps->_size; i > 0; i--) //i表示搬移到的目标位置(以上两个含义不同哦!)
ps->_array[i + 1] = ps->_array[i];
}
//插入元素
ps->_array[0] = data;
ps->_size++;
#endif
SeqListInsert(ps, 0, data);
}
void SeqListPopFront(PSeq ps){
#if 0
if (SeqListEmpty(ps))
return;
for (int i = 1; i < ps->_size; ++i)
ps->_array[i-1] = ps->_array[i];
ps->_size--;
#endif
SeqListErase(ps, 0);
}
void SeqListInsert(PSeq ps, int pos, DataType data){
assert(ps);
if ( pos < 0 || pos>ps->_size)
return;
//检测有无空间
//搬移
for (int i = ps->_size - 1; i >= pos; i--)
ps->_array[i+1] = ps->_array[i];
ps->_array[pos] = data;
ps->_size++;
}
void SeqListErase(PSeq ps, int pos){
assert(ps);
if (pos < 0 || pos >= ps->_size)
return; for (int i = pos + 1; i < ps->_size; ++i)
ps->_array[i - 1] = ps->_array[i];
ps->_size--;
}
int SeqListFind(PSeq ps, DataType data){
assert(ps);//保证存在
for (int i = 0; i < ps->_size; i++){
if (ps->_array[i] = data);
return i;
}
return -1;
}
int SeqListSize(PSeq ps){
assert(ps);
return ps->_size;
}
int SeqListCapacity(PSeq ps){
assert(ps);
return ps->_capacity;
}
int SeqListEmpty(PSeq ps){
assert(ps);
return 0 == ps->_size;
}
void SeqListClear(PSeq ps){
assert(ps);
ps->_size = 0;
}
//移除第一个值为data的元素
void SeqListRemove(PSeq ps, DataType data){
SeqListErase(ps, SeqListFind(ps, data));
}
//移除所有值为data的元素
void SeqListRemoveAll(PSeq ps, DataType data){
int pos = -1;
while (-1 != (pos = SeqListFind(ps, data))){
SeqListErase(ps, pos);
}
}
void SeqListDestroy(PSeq ps){
if (ps->_array){
free(ps->_array);
ps->_array = NULL;
ps->_capacity = 0;
ps->_size = 0;
}
}
void ChackCapacity(PSeq ps){
assert(ps);
if (ps->_size == ps->_capacity){
int newCapacity = ps->_capacity * 2;
int* pTemp = (DataType*)malloc(newCapacity*sizeof(DataType));
if (NULL == pTemp){
assert(0);
return;
}
for (int i = 0; i < ps->_size; ++i)
pTemp[i] = ps->_array[i];
free(ps->_array);
//更新参数
ps->_array = pTemp;
ps->_array = newCapacity;
}
}
void SeqListPrint(PSeq ps){
for (int i= 0; i < ps->_size; ++i)
printf("%d ", ps->_array[i]);
printf("\n");
}
void TestSeqList(){
SeqList s;
int pos = -1;
SeqListInit(&s, 10);//给定10个内存空间
SeqListPushBack(&s, 1);
SeqListPushBack(&s, 2);
SeqListPushBack(&s, 3);
SeqListPushBack(&s, 2);
SeqListPushBack(&s, 5);
SeqListPushBack(&s, 2);
SeqListPushBack(&s, 2);
printf("size = %d\n", SeqListSize(&s));
printf("capacity = %d\n", SeqListCapacity(&s));
SeqListPrint(&s);
SeqListPushBack(&s, 1);
printf("size = %d\n", SeqListSize(&s));
printf("capacity = %d\n", SeqListCapacity(&s));
SeqListPrint(&s);
SeqListPopBack(&s);
SeqListPrint(&s);
SeqListPushFront(&s, 0);
SeqListPrint(&s);
SeqListPopFront(&s);
SeqListPrint(&s);
SeqListInsert(&s,1,5);
SeqListPrint(&s);
pos = SeqListFind(&s, 5);
if (pos != -1)
printf("5 is in %d !!\n", pos);
else
printf("5 is not in %d !!\n", pos);
SeqListErase(&s, 1);
pos = SeqListFind(&s, 5);
if (pos != -1)
printf("5在 %d !!", pos);
else
printf("5不在 %d !!", pos);
SeqListPrint(&s);
printf("size = %d\n", SeqListSize(&s));
printf("capacity = %d\n", SeqListCapacity(&s));
SeqListDestroy(&s);
}
int main(){
TestSeqList();
system("pause");
return 0;
}
看到上面程序是不是很头疼,哈哈哈~当然还有啦,头文件可是不能缺少哒
#pragma once
//顺序表结构:
//数组
//静态顺序表:元素个数受限
#if 0
typedef int DataType;
#define MAX_SIZE 100
struct SeqList{
DataType _array[MAX_SIZE];//用来存储顺序表中的元素(最多的个数)
int _size; //顺序表中有效元素的个数
};
#endif
//动态顺序表:元素个数不受限【主要的*****】
typedef int DataType;
typedef struct SeqList{
DataType* _array;
int _capacity;//顺序表总大小
int _size;//顺序表中有效元素的个数
}SeqList, *PSeq;//加了typedef后SeqList就是一个类型别名
//不加typedef后SeqList变成一个结构体类型变量
//typedef struct SeqList SeqList;//取别名
//typedef struct SeqList* PSeqList;//同上
void SeqListInit(PSeq ps, int capacity);//初始化 capacity容量大小
void SeqListPushBack(PSeq ps, DataType data);//尾插(放元素)
void SeqListPopBack(PSeq ps);//尾删
//尾插和尾删时间复杂度都是O(1),在size的位置,size++就可以了,不需要搬移元素
//头插和头删时间复杂度都是O(N),在起始位置插一个元素,整体向后移一个位置
//以上性能太差,可以用Insert、Erase可以任意插入
void SeqListPushFront(PSeq ps, DataType data);//头插(分三步)
void SeqListPopFront(PSeq ps);
void SeqListInsert(PSeq ps, int pos, DataType data);
void SeqListErase(PSeq ps, int pos);
//以上两个时间复杂度最差情况为0(N)
int SeqListFind(PSeq ps, DataType data);//整体遍历一次
int SeqListSize(PSeq ps);
int SeqListCapacity(PSeq ps);
void SeqListClear(PSeq ps);
void SeqListRemove(PSeq ps,DataType data);//顺序表中一处第一个值为data的元素
void SeqListRemoveAll(PSeq ps, DataType data);
void ChackCapacity(PSeq ps);
int SeqListEmpty(PSeq ps);
void SeqListDestroy(PSeq ps);//顺序表销毁
void TestSeqList();
~bye~