顺序表
顺序表
c
#include<stdio.h>
#define MAXSIZE 100
typedef int ElemType;
//顺序表
typedef struct {
ElemType data[MAXSIZE];
int length;
}SeqList;
思路
- 顺序表本质来说是一个存储的介质,所以先定义一个数组来存储数据表中的元素,还得存储数组有多长.所以得用到结构体的方式.
分析代码
-
第二行是定义一个宏做简单的替换 (相当于MAXSIZE=100).
-
第三行为typedef用于为已有的数据类型定义别名,所以就是int的别名为ElemType.
-
第五行为同上,为结构体定义别名SeqList.
-
第六行为定义一个ElemType类型的数组用于存储数据表的元素(相当于int data [100]).
-
第七行为要定义一个数据表的长度.
-
typedef关键自定义结构体时可写为:typedef struct{}结构体名;.
静态初始化
c
//静态初始化
void initList(SeqList* L)
{
L->length = 0;
}
思路
- 要让顺序表初始化就只需要把length给赋值为0.
- 原因在后面能体现出来.
分析代码
- 这个为一个函数不需要返回值的.
- 调用时传入顺序表的地址即可.
- L->length就是在顺序表地址中找length并把它赋值为0.
动态初始化
c
#include<stdio.h>
#include<malloc.h>
#define MAXSIZE 100
typedef int ElemType;
typedef struct {
ElemType*data;
int length;
}SeqList;
//动态分配内存地址初始化
SeqList* initList() {
SeqList* L = (SeqList*) malloc(sizeof(SeqList));
L->data = (ElemType*)malloc(sizeof(ElemType) * MAXSIZE);
L->length = 0;
return L;
}
思路
- 这个跟静态初始化差不多,只是把存储位置改到堆内存中,这样更方便调用内存.
- malloc是在堆内存中开辟一空间的关键字
分析代码
- SeqList* L = (SeqList*) malloc(sizeof(SeqList));这句话是在堆内存中开辟出来一个顺序表的空间.
- L->data就是对data的初始化,让data在堆内存中开辟出400字节的空间,也就是(ElemType) * MAXSIZE.
- L->length = 0;让length初始化.
尾部添加
c
//尾部添加
int appendElem(SeqList*L,ElemType e)
{
if(L->length>=MAXSIZE)
{
printf("顺序表已满\n");
return 0;
}
L->data[L->length]=e;
L->length++;
return 1;
}
思路
- 顺序表如其名,需从尾部添加.
- 应该传入这个顺序表的地址和要传入的数据.
- 再来判断一下数据表是否已经满了如果满了就不让再传.
分析代码
- 判断length是否等于最大值如果等于就提示并且结束循环 length既可以当做顺序表的下标又可以当做顺序表的位数(假如现在有60个数据存进去了那么length=60,那么再存下一个的时候就存在data[60]里)
- 如果没有就继续往下执行,让data[length]=e,这个e就是传进来的数据.
- 存完以后让length再加1好进行下一次的存入.
遍历
c
//遍历
void listElem(SeqList* L)
{
for (int i = 0; i < L->length; i++)
{
printf("%d ", L->data[i]);
}
printf("\n");
}
思路
- 遍历就是需要把顺序表的元素都输出出来.
- 所以需要借助for循环,定义一个i让i<length这样就可以打印出来所有已添加的元素.
分析代码
- 传入顺序表的地址,用顺序表里的length的属性来遍历每一个元素.
插入
c
//插入
int insertElem(SeqList* L, int pos, ElemType e)
{
if(pos<L->length){
for(int i=length-1;i>=L->pos-1;i--){
L->data[i+1]= L->data[i];
}
L->data[pos-1]=e;
L->length++;
}
return 1;
}
思路
- 插入要先知道要插入的元素以及插入的位置,所以把(int pos, ElemType e)这个传入进去.
- 更需要知道顺序表的位置所以传入*L.
- 插入要确定插入的位置是否大于length也就是得小于length才能叫做插入.
- 插入的核心做法就是把要插入的位置空出来也就是把插入位置以后的所有元素的索引都加一.
分析代码
- 输入顺序表的地址,要插入的位置,要插入的数值.
- 确定pos的值比length小这样就继续往下.
- 开始循环从最后一位data[length-1]开始先后赋值.目的就是把目标位置空出来.
- 再将值赋值到目标位置,在让length加一.
删除
c
//删除
int deleteElem(SeqList*L,int pos,ElemType*e)
{
*e=L->data[pos-1];
if(pos<L->length){
for(int i=pos;i<length;i++){
L->data[i-1]=L->data[i];
}
}
L->length--;
return 1;
}
思路
- 删除要输入顺序表的地址和元素所在位置.
- 删除的本质其实就是把代码都往前挪一个,也就是把要删除的那个元素的位置给赋值成后面那一位,之后以此类推.
- 最后因为顺序表少了一个元素所以得让length减一.不用再将最后一位的元素给清空.新的元素将赋值到那个位置.
- 其实这个跟插入很相似.
分析代码
- 输入顺序表的地址和要删除位置.
- 在输入一个ElemType类型的指针,这是为了传出要删除的值,*e = L->data[pos - 1];.
- 判断输入进来的pos是否小于总体长度如果小于则继续往下.
- for循环让后一位的值覆盖前一位的值.
- 因为删除了一个元素所以length减一.
查找
c
//查找
int findElem(SeqList*L,ElemType e)
{
for(int i=0;i<L->length;i++){
if(L->data[i]==e){
return i+1;
}
}
return 0;
}
思路
- 查找要输入顺序表的地址和要查找的值.
- 遍历顺序表每一项,如果有跟值相等的就停止遍历,并返回所在位置.
分析代码
- 输入顺序表的地址和要查找的值.
- for循环每一个元素,之后再用if来判断循环的是否等于要查找的值,如果等于就返回当前索引加一就得到位置了.
- 如果一直循环不到就返回0.
在main函数中的应用
静态
c
int main() {
//初始化动态顺序表list
SeqList list;
initList(&list);
//在尾部添加元素
appendElem(&list, 10);
appendElem(&list, 20);
appendElem(&list, 30);
appendElem(&list, 40);
appendElem(&list, 50);
//插入元素
insertElem(&list, 3, 100);
//遍历数组
listElem(&list);
//删除元素
ElemType num;
deleteElem(&list, 2, &num);
printf("被删除的%d\n", num);
//查找元素
printf("%d", findElem(&list, 50));
}
动态
c
int main() {
//初始化动态顺序表list
SeqList *list= initList();
//在尾部添加元素
appendElem(list, 10);
appendElem(list, 20);
appendElem(list, 30);
appendElem(list, 40);
appendElem(list, 50);
//插入元素
insertElem(list, 3, 100);
//遍历数组
listElem(list);
//删除元素
ElemType num;
deleteElem(list, 2, &num);
printf("被删除的%d\n",num);
//查找元素
printf("%d", findElem(list, 50));
}
如哪里有问题请指出来我好及时修改谢谢.