基本操作
InitList(&L)
;初始化表。构造一个空的线性表L,分配内存空间DestroyList(&L)
:销毁操作。销毁线性表,并释放线性表L所占用的内存空间ListInsert(&L,i,e)
:插入操作。在表L中的第i个位置插入指定元素eListDelete(&L,i,&e)
:删除操作。删除表L中第i个位置的元素,并用e返回删除元素的值LocateElem(L,e)
:按值查找操作。在表L中查找具有给定关键字值的元素GetElem(L,i)
:按位查找操作。获取表L中第i个位置的元素的值其他常用操作
Length(L)
:求表长。返回线性表L中数据元素的个数PrintList(L)
:输出操作。按前后顺序输出线性表L的所有元素值Empty(L)
:判空操作。若L为空表,返回true,否则返回false#define MaxSize 50 //线性表的最大长度
typedef struct {
ElemType data[MaxSize]; //顺序表的元素
int length; //顺序表的当前长度
}SqList; //顺序表的类型定义
#define InitSize 50 //顺序表的初始长度
//动态分配
typedef struct {
ElemType* data; //指针动态分配数组的指针
int maxsize; //顺序表的最大容量
int length; //顺序表的当前长度
}SeqList;
L.data = (ElemType*)malloc(sizeof(ElemType) * InitSize); //C语言初始动态分配
2. C++:new、delete关键字
```C++
L.data = new int[InitSize];
插入
ListInsert(&L,i,e)
:插入操作。在表L中第i个位置上插入指定元素bool ListInsert(SqList& L, int i, int e){
if (i<1 || i>L.length + 1) { //判断i的范围是否有效
return false;
}
if (L.length >= MaxSize) { //当前存储空间已满,不能插入
return false;
}
for (int j = L.length; j >= i; j--) { //将第i个元素及之后的元素后移
L.data[j] = L.data[j - 1];
}
L.data[i - 1] = e; //在位置i处放e
L.length++; //长度加1
return true;
}
删除
bool ListDelete(SqList& L, int i, int& e){
if (i<1 || i>L.length + 1) { //判断i的范围是否有效
return false;
}
e = L.data[i - 1]; //将被删除的元素赋值给e
for (int j = i; j < L.length; j++) { //将第i个位置后的元素前移
L.data[j - 1] = L.data[j];
}
L.length--; 线性表长度减1
return true;
}
按位查找
GetElem(L,i)
:按位查找操作。获取表L中第i个位置的元素的值int GetElem(SqList L, int i){
return L.data[i - 1];
}
int GetElem(SeqList L, int i){
return L.data[i - 1];
}
按值查找
LocateElem(L,e)
:按值查找操作。在表L中查找具有给定关键字值的元素int LoacteElem(SqList L, int e){
int i;
for (i = 0; i < L.length; i++) {
if (L.data[i] == e) { //"=="不可以用于比较两个结构体
return i + 1; //下标为i的元素值等于e,返回其位序i+1
}
}
return 0; //退出循环,说明查找失败
}
typedef struct LNode { //定义单链表结点类型
int data; //每个结点存放一个指针元素
struct LNode* next; //指针指向下一个结点
}LNode, * LinkList;
bool InitList(LinkList& L){
L = NULL; //空表,暂时没有任何结点
return true;
}
bool InitList(LinkList& L) {
L = (LNode*)malloc(sizeof(LNode)); //分配一个头结点
if (L == NULL) {
return false;
}
L -> next = NULL; //头结点之后暂时还没有结点
return true;
}
按位序插入(带头结点)
ListInsert(&L,i,e)
:插入操作。在表L中的第i个位置上插入指定元素ebool ListInsert(LinkList &L, int i, ElemType e){
if(i<1){
return false;
}
LNode *p; //指针p指向当前扫描的结点
int j=0; //当前p指向的是第几个结点
p=L; //L指向头结点,头结点是第0个结点(不存储数据)
while(p!=NULL && jnext;
j++;
}
if(p==NULL){ //i值不合法
return false;
}
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p-next=s; //将结点s连到p之后
return true; //插入成功
}
按位序插入(不带头结点)
ListInsert(&L,i,e)
:插入操作。在表L中的第i个位置上插入指定元素ebool ListInsert(LinkList &L, int i, ElemType e){
if(i<1){
return false;
}
if(i==1){ //插入第i个结点的操作与其他结点不同
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=L;
L=s; //头指针指向新结点
return true; //插入成功
}
LNode *p; //指针p指向当前扫描的结点
int j=1; //当前p指向的是第几个结点
p=L; //p指向第1个结点(不是头结点)
while(p!=NULL && jnext;
j++;
}
if(p==NULL){ //i值不合法
return false;
}
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p-next=s; //将结点s连到p之后
return true; //插入成功
}
指定结点的后插操作
//在p结点之后插入元素e
bool InsertNextNode(LNode *p, ElemType e){
if(p==NULL){
return false;
}
LNode *s=(LNode *)malloc(sizeof(LNode));
if(s==NULL){ //内存分配失败
return false;
}
s->data=e; //用结点s保存数据元素e
s->next=p->next;
p->next=s; //将结点s连接到p之后
return true;
}
指定元素的前插操作
//在p结点之前插入元素e
bool InsertPriorNode(LNode *p, ElemType e){
if(p==NULL){
return false;
}
LNode *s=(LNode *)malloc(sizeof(LNode));
if(s==NULL){ //内存分配失败
return false;
}
s->next=p->next;
p->next=s; //将结点s连接到p之后
s->data=p->data; //将p中的元素复制到s中
p->data=e; //p中元素覆盖为e
return true;
}
按位序删除(带头结点)
ListDelete(&L,i,&e)
;删除操作,删除表L中第i个位置的元素,并用e返回元素的值bool ListDelete(LinkList &L,int i,ElemType &e){
if(i<1){
return false;
}
LNode *p; //指针p指向当前扫描到的结点
int j=0; //当前p指向的是第几个结点
p=L; //L指向头结点,头结点是第0个结点 (不存数据)
while (p!=NULL & jnext;
j++;
}
if(p==NULL){ //i值不合法
return false;
}
if(p->next == NULL){ //第i-1个结点之后已无其他结点
return false;
}
LNode *q=p->next; //令q指向被删除结点
e = q->data; //用e返回元素的值
p->next=q->next; //将*q结点从链中“断开”
free(q); //释放结点的存储空间
return true; //删除成功
}
指定结点的删除
//删除指定结点p
bool DeleteNode (LNode *p){
if (p==NULL){
return false;
}
LNode *q=p->next; //令q指向*p的后继结点
p->data=p->next->data; //和后继结点交换数据域
p->next=q->next; //将*q结点从链中“断开”
free(q); //释放后继结点的存储空间
return true;
}
如果p是最后一个结点,只能从表头开始寻找p的前驱,时间复杂度O(n)
按位查找
GetElem(L,i)
:按位查找操作。获取表L中第i个位置的元素的值//按位查找,返回第i个元素(带头结点)
LNode *GetElem(LinkList, int i){
if(i<0){
return NULL;
}
LNode *p; //指针p指向当前扫描到的结点
int j=0; //当前p指向的是第几个结点
p=L; //L指向头结点,头结点是第0个结点(不存储数据)
while (p!=NULL && jnext;
j++;
}
return p;
}
按值查找
LocateElem(L,i)
:按值查找操作。在表L中查找具有给定关键字值的元素//按值查找,找到数据域==e 的结点
LNode * LocateElem(LinkList L,ElemType e){
LNode *p = L->next;
//从第1个结点开始查找数据域为e的结点
while (p != NULL && p->data != e)
p = p->next;
return p; //找到后返回该结点指针,否则返回NULL
}
求表的长度
//求表的长度
int Length(LinkList L){
int len = 0; //统计表长
LNode *p = L;
while (p->next != NULL){
p = p->next;
len++;
}
return len;
开放式问题回答思路
问题: 请描述顺序表和链表的 bla bla bla… 实现线性表时,用顺序表还是链表好?
顺序表和链表的逻辑结构都是线性结构,都属于线性表但是二者的存储结构不同,顺序表采用顺序存储…(特点,带来的优点缺点): 链表采用链式存储…(特点、导致的优缺点)。由于采用不同的存储方式实现,因此基本操作的实现效率也不同。当初始化时…;当插入一个数据元素时…;当删除一个数据元素时…; 当查找一个数据元素时…