数据结构——线性表

要考试了大家,要考试了大家,要考试了大家,有点慌

目录

顺序存储结构(顺序表)

1.建立顺序表:

2.初始化线性表(也可以称为置空线性表)

3.销毁线性表(运算功能就是释放线性表L占用的内存空间)

4.判断线性表是否为空(是空返回true,不是空返回false)

5.返回线性表长度

6.输出线性表

7.求线性表中某个数据元素值

8.按元素查找

9.插入数据元素

10.删除数据元素

1.单链表声明

2.删除和插入节点的操作

a.插入节点的操作

b.删除节点的操作

3.建立单链表

a.头插法

b.尾插法

4.线性表的基本运算在单链表上的实现

a.初始化线性表

b.销毁线性表

c.判断线性表是否为空表

d.求线性表的长度

e.输出线性表

f.按序号求线性表中的元素

g.按元素值查找

h.插入数据元素

i.删除数据元素

双链表

1.双链表的类型声明

2.建立双链表

a.头插法

b.尾插法

循环链表


先总结一下书上要求掌握的线性表有关知识:

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;
}

循环链表

这里就不过多讲述这个了

  • 29
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值