要考试了大家,要考试了大家,要考试了大家,有点慌
目录
4.判断线性表是否为空(是空返回true,不是空返回false)
先总结一下书上要求掌握的线性表有关知识:
InitList(&L):初始化线性表,构造一个空的线性表L;
DestroyList(&L):销毁线性表,释放为线性表L分配的内存空间;
ListEmpty(L):判断线性表是否为空表,若L为空表,则返回真,否则返回假;
ListLength(L):求线性表的长度,返回L中的元素个数;
DispList(L):输出线性表,当线性表L不为空时,顺序输出L中各元素的值;
GetElem(L,i,&e):按序号求线性表中元素,用e返回L中第i个(1<=i<=n)个元素值;
LocateElem(L,e):按元素值查找,返回L中的第一个值为e相等的元素序号;
ListInsert(&L,i,e):插入元素,在L的第i个(1<=i<=n+1)位置插入一个新元素e;
ListDelete(&L,i,&e):删除元素,删除L的第i(1<=i<=n)个元素,并用e返回该元素值
顺序存储结构(顺序表)
1.在声明线性表的顺序存储结构类型时,定义一个data数组来存储线性表中的所有元素,还定义一个整型变量length来存储线性表的实际长度,并采用结构体类型SqList表示如下
typedef int ElemType;//定义ElemType为int类型
typedef struct{
ElemType data[MaxSize];//存放线性表中的元素
int length;//存放线性表的长度
}SqList;//顺序表类型
1.建立顺序表:
在这里先解释一个我之前没有搞很清楚的小概念:
在C++中,SqList *&L
表示一个指向指针的引用,通常用于函数参数传递。具体来说,SqList
是一个结构体或类,L
是一个指向SqList
类型的指针。通过&
符号表示引用,即传递指针的引用,可以在函数内部修改指针指向的地址,而不仅仅是修改指针指向的内容。这样做的好处是可以在函数内部直接修改指针指向的地址,而不需要返回指针,从而改变函数外部指针的指向。
(可能是我本人的原因吼,指针方面并没有掌握的太好,所以对于这个概念并不是很清楚,接下来上一道例题来解释一下这样做的好处吧)
#include <iostream>
using namespace std;
void func(int* ptr) {
ptr = new int(10);
cout << "In func, ptr = " << ptr << endl;
}
void func_ref(int*& ptr) {
ptr = new int(10);
cout << "In func_ref, ptr = " << ptr << endl;
}
int main() {
int* ptr = NULL;
cout << "In main, ptr = " << ptr << endl;
func(ptr);
cout << "After func, ptr = " << ptr << endl;
func_ref(ptr);
cout << "After func_ref, ptr = " << ptr << endl;
return 0;
}
输出结果为
In main, ptr = 0
In func, ptr = 0x7f861c8016d0
After func, ptr = 0
In func_ref, ptr = 0x7f861c8016d0
After func_ref, ptr = 0x7f861c8016d0
在这个例子中,func
函数接收一个指针的拷贝,在函数内部修改指针的指向,但是这个修改不会影响到函数外部的指针。而func_ref
函数接收一个指针的引用,在函数内部修改指针的指向,这个修改会影响到函数外部的指针。
同样的,在SqList *&L
中,传递的是一个指针的引用,可以在函数内部修改指针的指向,从而改变函数外部指针的指向
额。。。。接下来就是创建顺序表了,上菜
void CreateList(SqList *&L,ElemType a[],int n){//由a中的n个元素建立顺序表L
int i=0,k=0;//k表示L中的元素个数,初始个数为0
L=(SqList*)malloc(sizeof(SqList));//分配存放线性表的空间
while(i<n){
L->data[k]=a[i];
k++;i++;
}
L->length=k;//设置顺序表长度为k
}
2.初始化线性表(也可以称为置空线性表)
void InitList(SqList *&L){
L=(SqList*)malloc(sizeof(SqList));
L->length=0;//作用就是置空
}
3.销毁线性表(运算功能就是释放线性表L占用的内存空间)
void DestoryList(SqList *&L){
free(L);//释放L所指的顺序表空间
}
4.判断线性表是否为空(是空返回true,不是空返回false)
bool ListEmpty(SqList *L){
return(L->length==0);
}
5.返回线性表长度
int ListLength(SqList *L){
return (L->length);
}
6.输出线性表
void DispList(SqList *L){
for(int i=0;i<L->length;i++)
printf("%d",L->data[i]);
printf("\n");
}
7.求线性表中某个数据元素值
bool GetElem(SqList *L,int i,ElemType &e){//引用形参e返回L中第i个元素的值
if(i<1||i>L->length) return false;
e=L->data[i-1];
return true;
}
8.按元素查找
int LocateElem(SqList *L,ElemType e){
int i=0;
while(i<L->length&&L->data[i]!=e){
i++;
}
if(i>=L->length) return 0;
else return i+1;//找到后返回元素的逻辑序号
}
9.插入数据元素
bool ListInsert(SqList *&L,int i,ElemType e){
int j;
if(i<1||i>L->length+1){
return false;
}
i--;//将顺序表序号化为物理序号
for(j=L->length;j>i;j--){
L->data[i]=L->data[j-1];
}
L->data[i]=e;
L->length++;
return true;//成功插入返回true
}
10.删除数据元素
bool ListDelete(SqList *&L,int i,ElemType &e){
int j;
if(i<1||i>L->length){
return false;
}//这一步的主要作用就是要排除输入i错误,超值,小于零等特殊情况的出现
i--;
e=L->data[i];
for(j=i;j<L->length-1;j++){
L->data[i]=L->data[j+1];
}
L->length--;
return true;
}
1.单链表声明
typedef struct LNode{
ElemType data;
struct LNode *next;
}LinkNode;
//为了简单,假设ElemType为int类型
typedef int ElemType;
2.删除和插入节点的操作
a.插入节点的操作
s->next=p->next;
p->next=s;//将s插入链表p中
b.删除节点的操作
p->next=p->next->next;
而在一般情况下,在删除一个节点后还需要释放其存储空间,实现删除上述节点并释放其存储空间,语句描述如下:
q=p->next;//q临时保存被删节点
p->next=q->next;//从链表中删除节点q
free(q);//释放节点q的空间
3.建立单链表
a.头插法
void CreateListF(LinkNode *&L,ElemType a[],int n){
LinkNode *s;
L=(LinkNode*)malloc(sizeof(LinkNode));
L->next=NULL;
for(int i=0;i<n;i++){//循环建立数据节点s
s=(LinkNode*)malloc(sizeof(LinkNode));
s->data=a[i];
s->next=L->next;//将节点s插入到原首节点之前,头节点之后
L->next=s;
}
}
b.尾插法
void CreateListR(LinkNode *&L,ElemType a[],int n){
LinkNode *s,*r;
L=(LinkNode*)malloc(sizeof(LinkNode));//创建头节点
r=L;//r始终指向尾节点,初始时指向头节点
for(int i=0;i<n;i++){//循环建立数据节点
s=(LinkNode*)malloc(sizeof(LinkNode));
s->data=a[i];
r->next=s;//将节点s插入r之后
r=s;
}
r->next=NULL;//节点最后一个置空
}
4.线性表的基本运算在单链表上的实现
a.初始化线性表
void IniList(LinkNode *&L){
L=(LinkList*)malloc(sizeof(LinkNode));//创建头节点
L->next=NULL;
}
b.销毁线性表
void DestroyList(LinkNode *&L){
LinkNode *pre=L,*p=L->next;//pre指向节点p的前驱节点
while(p!=NULL){//遍历单链表L
free(pre);//释放pre节点
pre=p;//pre,p同步后移一个节点
p=pre->next;
}
free(pre);//循环结束后p为NULL,pre指向尾节点,继续释放
}
c.判断线性表是否为空表
bool ListEmpty(LinkNode *L){
return(L->next==NULL);
}
d.求线性表的长度
int ListLength(LinkNode *L){
int n=0;
LinkNode *p=L;
while(p->next!=NULL){
n++;
p=p->next;
}
return(n);
}
e.输出线性表
void DispList(LinkNode *L){
LinkNode *p=L->next;
while(p!=NULL){
printf("%d",p->data);
p=p->next;
}
printf("\n");
}
f.按序号求线性表中的元素
bool GetElem(LinkNode *L,int i,ElemType &e){
int j=0;
LinkNode *p=L;
if(i<=0) return false;
while(j<i&&p!=NULL){
j++;
p=p->next;
}
if(p==NULL){
return false;
}
else{
e=p->data;
return true;
}
}
g.按元素值查找
int LocateElem(LinkNode *L,ElemType e){
int i=1;
LinkNode *p=L->next;
while(p!=NULL&&p->data!=e){
p=p->next;
i++;
}
if(p==NULL){
return(0);
}
else{
return i;
}
}
h.插入数据元素
bool ListInsert(LinkNode *&L,int i,ElemType e){
int j=0;
LinkNode *p=L,*s;
if(i<=0) return false;
while(j<i-1&&p!=NULL){
j++;
p=p->next;
}
if(p==NULL){
return false;
}
else{
s=(LinkNode*)malloc(sizeof(LinkNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
}
i.删除数据元素
bool ListDelete(LinkNode *&L,int i,ElemType &e){
int j=0;
LinkNode *p=L,*q;
if(i<=0) return false;
while(j<i-1&&p!=NULL){
j++;
p=p->next;
}
if(p==NULL){
return false;
}
else{
q=p->next;
if(q==NULL){
retrun false;
}
e=q->data;
p->next=q->next;
free(q);
return true;
}
}
双链表
1.双链表的类型声明
typedef struct DNode{
ElemType data;
struct DNode *prior;//指向前驱节点
struct DNode *next;//指向后继节点
}DLinkNode;
2.建立双链表
a.头插法
void CreateListF(DLinkNode *&L,ElemType a[],int n){
DLinkNode *s;
L=(DLinkNode*)malloc(sizeof(DLinkNode));//创建头结点
L->piror=L->next=NULL;//前后指针域置为NULL
for(int i=0;i<n;i++){
s=(DLinkNode*)malloc(sizeof(DLinkNode));
s->data=a[i];
s->next=L->next;
if(L->next!=NULL){
L->next->prior=s;
}
L->next=s;
s->prior=L;
}
}
b.尾插法
void CreateListR(DLinkNode *&L,ElemType a[],int n){
DLinkNode *s,*r;
L=(DLinkNode*)malloc(sizeof(DLinkNode));
r=L;
for(int i=0;i<n;i++){
s=(DLinkNode*)malloc(sizeof(DLinkNode));
s->data=a[i];
r->next=s;
s->prior=r;
r=s;
}
r->next=NULL;
}
循环链表
这里就不过多讲述这个了