线性表的基础操作
1.创建线性表
2.销毁线性表
3.清空线性表
4.检查线性表是否为空
5.返回线性表的数据元素个数
6.返回线性表中指定位置的元素的值
7.找到符合条件的元素,返回其位置
8.返回线性表中指定元素的前一个元素的位置
9.返回线性表中指定元素的后一个元素的位置
10.在线性表指定位置插入一个元素
11.删除线性表中指定位置的元素
12.遍历线性表
线性表的两种存储结构
1.顺序存储结构
2.链式存储结构
线性表的顺序存储结构C语言实现
首先是结构体:
typedef int elemtype;
typedef struct List1
{
elemtype* data;
int lenth;
int listsize;
}List1,*Plist;
1.创建线性表
//lenth表示线性表最大的存储空间
int InitList1(Plist& list, int lenth)
{
list = (Plist)malloc(sizeof(List1));
if (list == NULL ) return 1;
//如果空间申请失败返回1(当然,基本上不会出现问题)
list->data = NULL;
list->data = (elemtype*)malloc(sizeof(elemtype) * lenth);
if ( list->data == NULL) return 1;
//如果空间申请失败返回1(同理)
list->lenth = 0;
list->listsize = lenth;
return 0;
//正常结束返回0
}
2.销毁线性表
int DestroyList1(Plist& list)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return 1;//如果线性表本身就是不存在返回1
}
if((list->data)!=NULL)
free(list->data);
free(list);
list = NULL;
return 0;
}
3.清空线性表
int ClearList1(Plist& list)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return 1;
}
list->lenth = 0;
return 0;
}
4.检查线性表是否为空
int List1Empty(Plist& list)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return -1;
}
if (list->lenth == 0) return 1;//线性表为空返回1
else return 0;//不为空返回0
}
5.返回线性表数据元素的个数
int List1Length(Plist& list)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return -1;
}
return list->lenth;
}
6.返回线性表中指定位置的元素的值
//找到指定位置,并将元素的值放入e中
int GetElemList1(Plist& list,int i,elemtype &e)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return 1;
}
if (i >= list->lenth)
{
printf_s("该位置没有元素\n");
return 2;
}
e = list->data[i];
return 0;
}
7.找到符合条件的元素,返回其位置
//自定义比较函数,如果啊a<b返回1
bool compare(elemtype a, elemtype b)
{
return a < b;
}
//该处知识点涉及——函数指针,很少使用,但是也需要了解
bool (*p)(elemtype a, elemtype b) = compare;
//查找符合条件的元素,并返回
int LocateElemList1(Plist& list, elemtype e, bool (*compare)(elemtype a, elemtype b))
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return -1;
}
for (int i = 0; i <= list->lenth; i++)
{
if (compare(e, list->data[i]))
{
return i;
//compare 表示如果a<b则为1;结果返回的就是线性表中第一个比e小的数字的位置
}
}
return -2;//没有比e小的数字则返回-2
}
函数指针的用法我会在这篇文章的最后简单调用一下给你们看。
对于顺序结构的线性表来说,查找元素的前驱和后继意义不大,但我还是写上了,不过没有多少注释了,这部分看不看都可以。
8.返回线性表中指定元素的前一个元素的位置
int PriorElem(Plist& list, elemtype cur_e, elemtype& pre_e)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return 1;
}
if (list->lenth <= 1)
{
if (list->lenth == 0)
{
printf_s("List is empty\n");
return 2;
}
else if (list->lenth == 1)
{
printf_s("Can't find the precursor, because there's only one\n");
return 3;
}
}
for (int i = 0; i < list->lenth; i++)
{
if (cur_e == list->data[i])
{
if (i != 0)
{
pre_e = i - 1;
return 0;
}
else
{
printf_s("Can't find the precursor, because it's the first\n");
return 4;
}
}
}
printf_s("Can't find the precursor because there's no such element\n");
return 5;
}
9.返回线性表中指定元素的后一个元素的位置
int NextElem(Plist& list, elemtype cur_e, elemtype& next_e)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return 1;
}
if (list->lenth <= 1)
{
if (list->lenth == 0)
{
printf_s("List is empty\n");
return 2;
}
else if (list->lenth == 1)
{
printf_s("Can't find the successor, because there's only one\n");
return 3;
}
}
for (int i = 0; i < list->lenth; i++)
{
if (cur_e == list->data[i])
{
if (i != list->lenth-1)
{
next_e = i + 1;
return 0;
}
else
{
printf_s("Can't find the successor, because it's the last one\n");
return 4;
}
}
}
printf_s("Can't find the successor because there's no such element\n");
return 5;
}
10.在线性表指定位置插入一个元素
//指定位置之前插入元素
int List1Insert(Plist& list, int numth, elemtype e)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return 1;
}
if (list->lenth == list->listsize)
{
printf_s("线性表已满,无法操作。\n");
return 2;
}
if (numth > list->lenth)
{
printf_s("该位置无效,无法操作\n");
return 3;
}
for (int i = list->lenth; i > numth; i--)
{
list->data[i] = list->data[i - 1];
}
list->data[numth] = e;
list->lenth++;
return 0;
}
11.删除线性表中指定位置的元素
int List1Delete(Plist& list, int numth, elemtype &e)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return 1;
}
if (list->lenth == 0)
{
printf_s("线性表已满\n");
return 2;
}
if (numth >= list->lenth)
{
printf_s("该位置没有元素\n");
return 3;
}
e = list->data[numth];
for (int i = numth; i < list->lenth-1; i++)
{
list->data[i] = list->data[i + 1];
}
list->lenth--;
return 0;
}
12.遍历线性表
void visit(elemtype e)
{
printf_s("%d ", e);
return;
}
void (*q)(elemtype a) = visit;
int List1Traverse(Plist& list,void (*visit1)(elemtype a))
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return 1;
}
if (list->lenth == 0)
{
printf_s("线性表为空\n");
return 2;
}
for (int i = 0; i < list->lenth; i++)
{
visit1(list->data[i]);
}
printf_s("\n");
return 0;
}
好了,以上为线性表顺序结构的基本操作,为了方便写入,我又写了一个插入的函数,这个函数只会在线性表的最后插入一个元素。
int List1push_back(Plist& list,elemtype e)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return 1;
}
if (list->lenth == list->listsize)
{
printf_s("线性表已满,无法操作。\n");
return 2;
}
list->data[list->lenth] = e;
list->lenth++;
return 0;
}
前面说过,要给你们看一下函数指针的调用。
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
int main()
{
Plist l;
int i;
InitList1(l, 10);
for (i = 0; i < 10; i++)
{
List1push_back(l, i);
}
//q在刚刚已经定义为全局变量
List1Traverse(l,*q);
return 0;
}
输出结果是 :0 1 2 3 4 5 6 7 8 9 \n
呼,好多啊。昨天写了一天,今天又整理了一上午,但感觉还是很值的,函数指针也是在整理复习的时候才知道。C语言很多地方确实没有C++好用,但是没办法,大家多数最开始的时候学的都是C语言,所以我先写了C语言的顺序表操作。
这一篇就写这一部分吧,下一篇会写C语言的链表实现。
对了,放一下总代码:
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include<malloc.h>
typedef int elemtype;
typedef struct List1
{
elemtype* data;
int lenth;
int listsize;
}List1,*Plist;
int InitList1(Plist& list, int lenth)
{
list = (Plist)malloc(sizeof(List1));
if (list == NULL ) return 1;
list->data = NULL;
list->data = (elemtype*)malloc(sizeof(elemtype) * lenth);
if ( list->data == NULL) return 1;
list->lenth = 0;
list->listsize = lenth;
return 0;
}
int DestroyList1(Plist& list)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return 1;
}
if((list->data)!=NULL)
free(list->data);
free(list);
list = NULL;
return 0;
}
int ClearList1(Plist& list)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return -1;
}
list->lenth = 0;
return 0;
}
int List1Empty(Plist& list)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return -1;
}
if (list->lenth == 0) return 1;
else return 0;
}
int List1Length(Plist& list)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
exit(-1);
}
return list->lenth;
}
int GetElemList1(Plist& list,int i,elemtype &e)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return 1;
}
if (i >= list->lenth)
{
printf_s("Out of list range\n");
return 2;
}
e = list->data[i];
return 0;
}
bool compare(elemtype a, elemtype b)
{
return a < b;
}
bool (*p)(elemtype a, elemtype b) = compare;
int LocateElemList1(Plist& list, elemtype e, bool (*compare)(elemtype a, elemtype b))
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return 1;
}
for (int i = 0; i <= list->lenth; i++)
{
if (compare(e, list->data[i]))
{
return i;//compare 表示如果a>b则为1;结果返回的就是线性表中第一个比e小的数字的位置
}
}
return -1;//没有比e小的数字则返回-1;
}
int PriorElem(Plist& list, elemtype cur_e, elemtype& pre_e)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return 1;
}
if (list->lenth <= 1)
{
if (list->lenth == 0)
{
printf_s("List is empty\n");
return 2;
}
else if (list->lenth == 1)
{
printf_s("Can't find the precursor, because there's only one\n");
return 3;
}
}
for (int i = 0; i < list->lenth; i++)
{
if (cur_e == list->data[i])
{
if (i != 0)
{
pre_e = i - 1;
return 0;
}
else
{
printf_s("Can't find the precursor, because it's the first\n");
return 4;
}
}
}
printf_s("Can't find the precursor because there's no such element\n");
return 5;
}
int NextElem(Plist& list, elemtype cur_e, elemtype& next_e)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return 1;
}
if (list->lenth <= 1)
{
if (list->lenth == 0)
{
printf_s("List is empty\n");
return 2;
}
else if (list->lenth == 1)
{
printf_s("Can't find the successor, because there's only one\n");
return 3;
}
}
for (int i = 0; i < list->lenth; i++)
{
if (cur_e == list->data[i])
{
if (i != list->lenth-1)
{
next_e = i + 1;
return 0;
}
else
{
printf_s("Can't find the successor, because it's the last one\n");
return 4;
}
}
}
printf_s("Can't find the successor because there's no such element\n");
return 5;
}
int List1Insert(Plist& list, int numth, elemtype e)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return 1;
}
if (list->lenth == list->listsize)
{
printf_s("线性表已满,无法操作。\n");
return 2;
}
if (numth > list->lenth)
{
printf_s("The location is not valid\n");
return 3;
}
for (int i = list->lenth; i > numth; i--)
{
list->data[i] = list->data[i - 1];
}
list->data[numth] = e;
list->lenth++;
return 0;
}
int List1Delete(Plist& list, int numth, elemtype &e)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return 1;
}
if (list->lenth == 0)
{
printf_s("The list is empty\n");
return 2;
}
if (numth >= list->lenth)
{
printf_s("The location is not valid\n");
return 3;
}
e = list->data[numth];
for (int i = numth; i < list->lenth-1; i++)
{
list->data[i] = list->data[i + 1];
}
list->lenth--;
return 0;
}
void visit(elemtype e)
{
printf_s("%d ", e);
return;
}
void (*q)(elemtype a) = visit;
int List1Traverse(Plist& list,void (*visit1)(elemtype a))
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return 1;
}
if (list->lenth == 0)
{
printf_s("The list is empty\n");
return 2;
}
for (int i = 0; i < list->lenth; i++)
{
visit1(list->data[i]);
}
printf_s("\n");
return 0;
}
int List1push_back(Plist& list,elemtype e)
{
if (list == NULL)
{
printf_s("线性表不存在\n");
return 1;
}
if (list->lenth == list->listsize)
{
printf_s("线性表已满,无法操作。\n");
return 2;
}
list->data[list->lenth] = e;
list->lenth++;
return 0;
}
int print(Plist &l)
{
int List1Traverse(Plist & l, void(*visit)(elemtype a));
List1Traverse(l,*q);
if (l != NULL)
printf_s("链表长度为:%d\n", l->lenth);
return 0;
}
int menu(Plist L)
{
int print(Plist &L);
printf_s("=====线性表C语言实现=====\n");
printf_s("1.创建表 2.删除表\n");
printf_s("3.初始化表 4.插入元素\n");
printf_s("5.删除元素 \n");
printf_s("=====线性表C语言实现=====\n");
print(L);
return 0;
}
int main()
{
int n,a,b;
Plist L=NULL;
menu(L);
while (scanf_s("%d", &n) != EOF)
{
switch (n)
{
case 1:
if (L == NULL)
{
printf_s("请输入链表的最大长度:");
scanf_s("%d", &a);
a=InitList1(L, a);
if (a == 0)
{
printf_s("创建成功,正在返回主菜单\n");
Sleep(1000);
system("cls");
break;
}
else
{
printf_s("创建失败,空间申请失败,正在返回主菜单\n");
break;
}
}
else
{
printf_s("操作失败!线性表已经存在!即将返回主菜单!\n");
Sleep(1000);
system("cls");
break;
}
case 2:
a=DestroyList1(L);
if(a==0)
printf_s("操作成功,即将返回主菜单!\n");
Sleep(1000);
system("cls");
break;
case 3:
if (L != NULL)
{
printf_s("请输入初始化的数目:");
scanf_s("%d", &a);
L->lenth = 0;
printf_s("请输入初始化的数组:");
for (int i = 0; i < a; i++)
{
scanf_s("%d", &b);
List1push_back(L, b);
}
printf_s("操作成功,即将返回主菜单!\n");
}
else printf_s("操作失败,链表不存在,即将返回主菜单!\n");
Sleep(1000);
system("cls");
break;
case 4:
if (L != NULL)
{
printf_s("请输入插入元素位置和元素值:");
scanf_s("%d%d", &a, &b);
a = List1Insert(L, a, b);
if (a == 0)
printf_s("操作成功,即将返回主菜单!\n");
}
else printf_s("操作失败,链表不存在,即将返回主菜单!\n");
Sleep(1000);
system("cls");
break;
case 5:
if (L != NULL)
{
printf_s("请输入删除元素的位置:");
scanf_s("%d", &a);
a = List1Delete(L, a, b);
printf_s("删除元素的值为%d\n", b);
if (a == 0)
printf_s("操作成功,即将返回主菜单!\n");
}
else printf_s("操作失败,链表不存在,即将返回主菜单!\n");
Sleep(1000);
system("cls");
break;
default:
printf_s("输入有误,请重新输入!");
Sleep(1000);
system("cls");
break;
}
menu(L);
}
}
#if 0
int main()
{
Plist l;
InitList1(l, 10);
for (int i = 0; i < 10; i++)
{
List1push_back(l, i);
}
List1Traverse(l,*q);
return 0;
}
#endif