线性表-c语言实现(1)
在大学的时候,我只是学了结构,并没有理会具体的实现,最近想写写。
当然,搁置了很久的c有些不太熟练了,还好脑子没坏掉,跟着网页上的写了些 ,除了有些让我吐槽的地方
编译环境 eclipse(c、c++版本),编译器 mingw
另外 我觉得代码实现是能更好的掌握某种结构他是怎么样做这件事情的,在实现之前,还是应该知道线性表做了什么比较好,例如线性表的位置计算可以看作是 中学的等差数列,另外 插入也好 删除也好,自己手写10个数字 如果你要插入 ,删除 怎么样移动,有了思路,实现不是一个大的问题。
写的很糟烂,包含了测试数据,和笔者遇到的坑。
------------------------------------------------
eclipse的这里实在赞,免去了我不少的麻烦
=========================
1,一些预定义的常量,看心情定义便可,我常常不认识大写的英文。
我非常想要 带编号又复制不上去的那个代码编辑区 不知道怎么做的 。
#include <stdio.h> #include <stdlib.h> #define TRUE 1 #define true 1 #define FALSE 0 #define false 0 #define OK 1 #define ok 1 #define ERROR 0 #define error 0 #define null NULL #define INFEASIBLE -1 #define infeasible -1 #define OVERFLOW -2 #define overflow -2 #define LIST_INIT_SIZE 10 #define LISTINCREMENT 10
2线性表结构体
typedef struct { int *elem; //定义了顺序表中元素类型的数组指针,指向顺序表存储空间的首地址 int length; //顺序表的长度(也即元素个数) int listsize; //当前分配给顺序表的存储容量 } SqList;
3初始化线性表
预先说明 (*L).len等价于L->len
int InitList(SqList *L) { //初始化线性表list L->elem = malloc(LIST_INIT_SIZE * sizeof(int)); printf(" malloc +++++++ size %d \n ", (int) L->elem); if (L->elem == 0) {//判定如果分配不成功则退出 exit(-1); } L->length = 0; L->listsize = LIST_INIT_SIZE; return ok; }
//malloc 初始化空间 转不转换没关系的 你需要的只是这么大的空间而已
这段代码是初始化你定义的结构体,首先按照预定义的空间,我这里面设定的是10,为了做扩充实验。
然后 申请这么大的空间 sizeof(int)是一个int占用的大小,
然后 sizeof(int)×LIST_INIT_SIZE就是10个int的大小,将他们的首地址赋值给L->elem
L->listsize 是这片空间的大小 L->是当前元素的数量
4线性表满的判定
int isListSize(SqList *L) { //判断 队满 //如果 满了 则0 否则1 if (L->listsize == L->length) { //如果分配空间=元素空间=队满 printf("nonononononononono"); return 0; } else return 1; }
5扩充线性表
int ReList(SqList *L) { //扩充 list printf("************************"); if (L->elem == 0) { exit(error); } int *q; q = realloc(L->elem, (L->listsize + LISTINCREMENT) * sizeof(int)); printf("\n this realloc +++++++ size %d \n ", (int) q); if (q != null) { L->elem = q; L->listsize += LISTINCREMENT; } return ok; }
这里面有一个很赞的方法 realloc ,他会判定如果可以直接扩充,那自然ok ,如果不能 ,则申请新空间,将原有数据复制过去。
它包含两个参数 realloc(原线性表首地址,新空间大小)
所以千万不要忘记 新空间大小=(L->listsize+ 扩展的大小)×sizeof(int)
另外 需要一个 新地址接收这个 新空间,因为万一有问题 没有赋值上呢?笔者就在这写出了问题。
判定下 没有问题就可以复制了;可以判定 如果q!=null 则执行L->elem=q;L->listsize+=10;
6判定插入位置的合法性
int ispoint(SqList *L, int x) { //判断插入元素的位置是否合法 if (x < 0 || x > L->length) { printf("x-- point error\n"); exit(overflow); } else { return 1; } }
给定位置x 如果他大于0 或者大于表中已有元素,则退出
讲道理 比如 有10个数据,我指定位置为11 我觉得是合理的,这里我很想写
x>L->length+1
在 后面的插入中 我先判定的是位置,后判定的是空间
感觉 插入 11 然后 现在Length==listsize 然后扩大空间,然后插入 没有任何位置啊
反而 如果不写 x>L->length+1 我是没办法在 队满的情况下 插入到最后的位置
但是 ,笔者计算位置 用的是 从0开始 所以x>L->length 即可。
7 插入元素
int ListInsert(SqList (*L), int x, int e) { //向第x个位置前面插入一个元素 int i = 0; ispoint(L, x); //判断插入位置 if (isListSize(L) == 0) { //判断队满 ReList(L);//满了就扩充 } for (i = L->length; i > x; i--) {//移动位置 L->elem[i] = L->elem[i - 1]; } L->elem[x] = e;//插入数据 L->length += 1;//更新元素个数 return ok; }
我看书上的算法蒙逼了,for处我不知道为什么需要指针,又不是链表。
我想说明 数组即指针!然后 不用那么麻烦。
8删除元素
int ListDel(SqList (*L), int x) { int i = 0; ispoint(L, x);//判定下删除的位置合法性 int e = L->elem[x];//先将 元素赋值给 e for (i = x + 1; i < L->length; i++) {//挨个移动 覆盖过去 L->elem[i] = L->elem[i + 1]; } L->length -= 1;//更新元素个数 return e;//返回删除的元素 }
又一个坑 我才不要写 int ListDel(SqList (*L),int x, int e) 他要是返回值是 e我也认
你是按照下标删除啊 ,首先 调用的时候 写一个没用的数据
进去了 e 确实赋值了 然后 return OK ~这是在逗我吧。
adt是adt 实现是实现。
9 测试数据
void outlist(SqList *L) { int i = 0; while (i < L->length) { printf("%d\t", (*L).elem[i]); i++; } printf("\n"); } void inlist(SqList *L, int len) { int i = 0; while (i < len) { L->elem[i] = i; L->length += 1; i++; } } int main(void) { SqList *list = malloc(sizeof(int)); //看着初始化总是黄色警告心烦 InitList(list); inlist(list, 10); outlist(list); printf("1 listsize:%d 2 length :%d \n", list->listsize, list->length); int p = 99; ListInsert(list, 10, p); printf("1 listsize:%d 2 length :%d \n", list->listsize, list->length); outlist(list); printf("this listdel %d\n", ListDel(list, 5)); printf("1 listsize:%d 2 length :%d \n", list->listsize, list->length); printf("ok"); return EXIT_SUCCESS; }
就是这样 插入是inlist 输出是outlist你要是喜欢 可以 手动插入或者随机数
main里面是测试数据 ;