线性表
线性表:零个或多个数据元素的有限序列。
线性表的长度:线性表元素的个数n(n>=0)当n=0时,称为空表。
在较复杂的线性表中,一个数据元素可以由若干个数据项组成。
关于线性表的顺序存储结构,可分为两种,一种为静态线性表的顺序存储结构即最大存储容量不能变,另一种为可以增加线性表容量的动态线性表存储结构。
以下代码为静态线性表的顺序存储结构及其基本操作:
#include <stdio.h>
#include <malloc.h>
#define MAXSIZE 20 /*存储空间初识分配量*/
typedef int ElemType; /*ElemType类型更具实际情况而定,这里假设为int*/
typedef struct
{
ElemType data[MAXSIZE]; /*数组存储数据元素,最大容量为MAXSIZE*/
int length; /*线性表当前长度*/
}SqList;
bool ListEmpty(const SqList* sl)
{
return sl->length ? false : true;
}
void ClearList(SqList* sl)
{
sl->length = 0;
}
int LocateElem(const SqList* sl, ElemType e)
{
for (int i = 0; i < sl->length; ++i)
{
if (sl->data[i] == e)
{
return i;
}
}
return -1;
}
int ListLength(const SqList* sl)
{
return sl->length;
}
/*
函数名 :ListInsert
功能描述 :在顺序表sl的i位置,插入新元素e
输入 :sl,i,e
sl,已存在顺序表
i,插入位置,范围 0 <= i <= sl->lenght
e,新元素
输出 :bool值,插入成功true,否则false
全局变量 :无
调用模块 :无
作者 :zhang haochen
日期 :2018-12-26
修改 :
修改日期 :
版本 :ver 1.0
*/
bool ListInsert(SqList* sl, int i, ElemType e)
{
if (sl->length == MAXSIZE || i < 0 || i > sl->length)
return false;
for (int j = sl->length - 1; j >= i; j--)
{
sl->data[j+1] = sl->data[j];
}
sl->data[i] = e;
sl->length += 1;
return true;
}
/*
函数名 :ListDelete
功能描述 :将顺序表sl的第i位置元素删除
输入 :sl,i
sl,已存在顺序表
i,插入位置,范围 0 <= i < sl->lenght
输出 :bret, bool值,删除成功true,否则false
全局变量 :无
调用模块 :无
作者 :zhang haochen
日期 :2018-12-26
修改 :
修改日期 :
版本 :ver 1.0
*/
bool ListDelete (SqList* sl, int i)
{
bool bret = true;
if (i < 0 || i >= sl->length)
bret = false;
else
{
for (int j = i; j < sl->length; ++j)
{
sl->data[j] = sl->data[j+1];
}
sl->length -= 1;
}
return bret;
}
void ShowList(const SqList*sl)
{
for (int i = 0; i < sl->length; ++i)
{
printf("%d,", sl->data[i]);
}
puts("\b;");
}
动态线性表的顺序存储结构相比静态的是可以在表长超出最大范围时可以增大线性表容量,下面为操作代码
#include <stdio.h>
#include <malloc.h>
typedef int ElemType;
typedef struct dynamiclist
{
ElemType* data; /*线性表数据起始地址*/
int length; /*线性表当前长度*/
int capicity; /*线性表容量*/
}dlist;
/*
函数名 :ListAddCapicity
功能描述 :增加线性表容量(将原先线性表容量翻倍)
输入 :sl
sl,已存在顺序表
输出 :无
全局变量 :无
调用模块 :无
作者 :zhang·haochen
日期 :2019-01-17
修改 :
修改日期 :
版本 :ver 1.0
*/
void ListAddCapicity(dlist* s1)
{
int newcapicity;
if (s1->capicity == 0)
newcapicity = 1;
else
newcapicity = 2 * s1->capicity;
s1->data = (ElemType*)realloc(s1->data, sizeof(ElemType)*newcapicity);
s1->capicity=newcapicity;
}
/*
函数名 :InitList
功能描述 :初始化线性表sl
输入 :sl
sl,已存在顺序表
输出 :无
全局变量 :无
调用模块 :ListAddCapicity
作者 :zhang·haochen
日期 :2019-01-17
修改 :
修改日期 :
版本 :ver 1.0
*/
void Initlist(dlist* s1)
{
s1->data = NULL;
s1->length=0;
s1->capicity = 0;
ListAddCapicity(s1);
}
/*
函数名 :ListEmepty
功能描述 :判断当前线性表是否为空,
输入 :sl
sl,已存在顺序表
输出 :若为空则返回true,否则返回false
全局变量 :无
调用模块 :无
作者 :zhang·haochen
日期 :2019 - 01 - 17
修改 :
修改日期 :
版本 :ver 1.0
*/
bool ListEmpty(const dlist* s1)
{
return s1->length ? false : true;
}
/*
函数名 :LocateElem
功能描述 :在线性表s1中查找与定值e相等的元素
输入 :sl,e
sl,已存在顺序表
输出 :如果查找成功,返回改元素的数组下标;否则返回-1表示失败
全局变量 :无
调用模块 :无
作者 :zhang·haochen
日期 :2019 - 01 - 17
修改 :
修改日期 :
版本 :ver 1.0
*/
int LocateElem(dlist* s1,ElemType e)
{
int i = 0;
for (i = 0; i < s1->length; i++)
{
if (*(s1->data + i) == e)
{
return i;
}
}
return -1;
}
/*
函数名 :ClearList
功能描述 :将线性表清空
输入 :sl
sl,已存在顺序表
输出 :无
全局变量 :无
调用模块 :无
作者 :zhang·haochen
日期 :2019 - 01 - 17
修改 :
修改日期 :
版本 :ver 1.0
*/
void ClearList(dlist* s1)
{
s1->length = 0;
}
/*
函数名 :ListLength
功能描述 :返回线性表的元素个数
输入 :sl,已存在顺序表
输出 :返回线性表的元素个数
全局变量 :无
调用模块 :无
作者 :zhang·haochen
日期 :2019 - 01 - 17
修改 :
修改日期 :
版本 :ver 1.0
*/
int ListLength(dlist* s1)
{
return s1->length;
}
/*
函数名 :ListInsert
功能描述 :在线性表第i个位置插入新元素e
输入 :sl,e,i
sl,已存在顺序表
输出 :插入成功返回bool类型,true,否则返回false
全局变量 :无
调用模块 :ListAddCapicity
作者 :zhang·haochen
日期 :2019 - 01 - 17
修改 :
修改日期 :
版本 :ver 1.0
*/
bool ListInsert(dlist* s1, int i,ElemType e)
{
if (i<0 || i>s1->length)
return false;
if (s1->length == s1->capicity)
{
ListAddCapicity(s1);
}
for (int j = s1->length - 1; j >= i; j--)
{
*(s1->data + j + 1) = *(s1->data + j);
}
*(s1->data + i) = e;
s1->length += 1;
return true;
}
/*
函数名 :ListDelete
功能描述 :删除线性表位置为i的元素
输入 :i,s1已存在顺序表
输出 :返回bool类型,删除成功返回true,删除失败返回false
全局变量 :无
调用模块 :无
作者 :zhang·haochen
日期 :2019 - 01 - 17
修改 :
修改日期 :
版本 :ver 1.0
*/
bool ListDelete(dlist* s1, int i)
{
bool boolret = true;
if (i < 0 || i >= s1->length)
boolret = false;
else
{
for (int j = i; j < s1->length; j++)
{
*(s1->data + j) = *(s1->data + j + 1);
}
s1->length -= 1;
}
return boolret;
}
/*
函数名 :ShowList
功能描述 :将线性表输出打印
输入 :s1已存在顺序表
输出 :无
全局变量 :无
调用模块 :无
作者 :zhang·haochen
日期 :2019 - 01 - 17
修改 :
修改日期 :
版本 :ver 1.0
*/
void ShowList(dlist* s1)
{
for (int i = 0; i < s1->length; i++)
{
printf("%d,",*(s1->data+i));
}
puts("\b;");
}
void ListDeleteByvalue(dlist* s1, ElemType e )
{
int i, j;
for (j = 0, i = 0; j < s1->length; j++)
{
if (*(s1->data+j)!=e)
{
*(s1->data + i) = *(s1->data + j);
i++;
}
}
s1->length = i;
}
int main()
{
dlist s1;
dlist* p = &s1;
Initlist(p);
ListInsert(p, 0, 1);
ListInsert(p,1,2);
ListInsert(p, 2, 3);
ListInsert(p, 3, 4);
ListInsert(p, 4, 3);
ShowList(p);
ListDeleteByvalue(p, 3);
ShowList(p);
return 0;
}
关于线性表的顺序存储结构操作为以上代码。下面练习几个程序
1.写出按值删除的函数,要求时间复杂度为O(n),空间复杂度为O(1)。
解题思路为:定义两个下标i,j都放在线性表第一个元素处,判断j所在元素是否为需要删除的元素,若不是则把j处元素值给i处,i与j各向后移动一位;若是则j移动到下一个不是待删除元素处,再将j处元素值给i处,并i与j各向后移动一位。重复,知道j越界,最后再将i的值赋给线性表的长度。则删除完成。
void ListDeleteByvalue(dlist* s1, ElemType e )
{
int i, j;
for (j = 0, i = 0; j < s1->length; j++)
{
if (*(s1->data+j)!=e)
{
*(s1->data + i) = *(s1->data + j);
i++;
}
}
s1->length = i;
/*s1是代表线性表的指针,e为待删除元素*/
。
2.动态线性表操作,按值替换功能,比如将表中值为5的元素替换为1,2,3(相当于多插入了2个元素)。要求算法时间复杂度为O(n),空间复杂度为O(1).
思路大概如下:可以先遍历一遍,这样可以统计出需要替换的元素个数,即可以得到替换后线性表的总长度。然后在进行插入。
代码如下:
/*
函数名 :ElemReplace
功能描述 :将制定值的线性表元素替换为一个或多个元素。
输入 :s1已存在顺序表,需要替换的元素e,还有要替换为的元素d
输出 :无
全局变量 :无
调用模块 :ListAddCapicity
作者 :zhang·haochen
日期 :2019 - 01 - 17
修改 :
修改日期 :
版本 :ver 1.0
*/
void ElemReplace(dlist* s1,ElemType e,ElemType d1,ElemType d2)
{
int count = 0;
for (int i = 0; i < s1->length; i++)
{
if (*(s1->data + i) == e)
{
count++;
}
}
while ((s1->length) + count>s1->capicity)
{
ListAddCapicity(s1);
}
int i, j;
for (int i = s1->length - 1, j = s1->length + count - 1; i >= 0; j--, i--)
{
if (*(s1->data + i) != e)
{
*(s1->data + j) = *(s1->data + i);
}
else
{
*(s1->data + j) = d2;
j--;
*(s1->data + j) = d1;
}
}
s1->length += count;
}
关于线性表的顺序存储就写到这了,接下来是线性表的链式存储了。