数据结构笔记(一)线性结构

数据结构

本笔记是根据数据结构与算法基础(青岛大学-王卓)归纳整理而成

本篇笔记是用markdown编写

如有侵权请联系我删除:209195687qq.com

注:转载请注明出处,谢谢!

"*"代表相对重要

类C语言补充

data(即数组名)和*data存放的是数组首地址

(ElemType*)表示强制类型转换成指针

线性表

顺序表示

顺序表的基本操作

//函数结果状态代码#define TRUE

#DEFINE ture 1

#DEFINE false 0

#define oK 1

#define ERROR0

#define INFEASIBLE -1

#define OVERFLOW -2 

//Status是函数的类型,其值是函数结果状态代码

typedef int status;

typedef char ElemType;


线性表L的初始化
status initlist_sq(sqlist &L){

L.elem=new ElemType[MAXSIZE];

if(!L.elem) exit(OVERFLOW);

L.legth=0;

return ok;

}
线性表L的销毁与清空
void destroylist(sqlist &L){

if(L.elem) delete L.elem; //释放存储地址空间(delete为c++语法)

}

void clearlist(sqlist &L){

L.length=0; 

}
L的长度及是否为空
int GetLength(SqList L){

return (L.length);

}

int lsEmpty(SqList L){

if (L.length==0) return 1;

else return o;
顺序表的取值
int GetElem(SqList L,int i,ElemType &e){

if (i<1||i>L.length)

return ERROR;

e=L.elem[i-1];

 return OK;
 }

**顺序表的值查找(顺序查找)

int LocateELem(SqList L ElemType e){

//在线性表L中查找值为e的数据元素,返回其序号(是第几

个元素)

for (i=0;i< L.length;i++)

if (L.elem[i]==e) return i+1;//查找成功,返回序号return 0; 

//查找失败,返回0
}

平均查找长度:

平均时间复杂度:

O(n)

特点:

​ 随机存取

**顺序表的插入

插入位置i:1<=i<=n+1

平均查找长度:

平均时间复杂度:

O(n)

**顺序表的删除

插入位置i:1<=i<=n

平均查找长度:

平均时间复杂度:

O(n)

顺序表的总结

链式表示

概念

1.无头结点表示空表:

2.有头结点表示空表:

3.头结点的好处:

4.特点:

​ 顺序存取

单链表

存储结构(类型定义):

typedef struct Lnode{
	ELEMTYPE data;
	struct londe *next;
	}Londe,*Linklist;

*Linklist表示指向这个结构块的指针

定义指针:

Linklist L / Lnode *L

基本操作(带头结点)
单链表的初始化

单链表是否为空

*单链表销毁包括头结点

一个辅助指针

image-20220321200219327

image-20220321200225176

*单链表清空

两个辅助指针

注:

while(L)等价于while(L!=null)

循环条件不能为while(q)

*单链表长度

一个辅助指针

**取值

一个辅助指针

1<=i<=n

while循环里跳出的情况:

p为null(i>j) j=i i<1 (即: j>i)

符合if条件的:

p为null(i>j) 或 i<1 (即: j>i)

注:此代码为伪代码

**查找

一个辅助指针

1<=i<=n

返回指针地址

同:
{
p=L->next;
while(p){
if(p->data=a)
return p;
p=p->next;
}
return p;
}

不成熟总结:
while(  ){
for(  )
}
等价于while(  &&  ) 

返回位置序号

平均查找长度:

平均时间复杂度:

O(n)

**插入 (之前)

两个辅助指针

1<=i<=n+1

vs对比

image-20220321200420667

平均时间复杂度:

O(n)

注:插入和删除操作的完整过程包括查找操作,查找操作是O(n),而单个插入和删除操作只是移动指针,只是O(1)

**删除

两个辅助指针

1<=i<=n

image-20220321200430771

解析:

p=L;j=0;

因为删除首元结点时要用到头结点,所以将L赋给p,而不是将L->next赋给p

while(p->next&&j<i-1):

①确保 q指向的地址不为null;如果是while(p&&j<i-1),当i=n+1时,q会指向第n+1个元素(即null),那么q->next就无意义(会报错)

while(p) p->next:p会指向第n+1个元素(即null)

while(p->next) p->next:p会指向第n个元素

②p指向第i个结点前驱的固定格式:(循环次数不重要,不需记忆)

p=L;j=0; while条件是j<i-1或j<=i-2 循环i-1次

p=L->next;j=1; while条件是j<i-1或j<=i-2 循环i-2次

p指向第i个结点的固定格式:

p=L;j=0; while条件是j<i或j<=i-1 循环i次

p=L->next;j=1; while条件是j<i或j<=i-1 循环i-1次

③if(!(p->next)||j>i-1) return error: 表示i不在1<=i<=n这个区间范围内,就return

结论:

p指向第i个结点前驱,while条件是j<i-1或j<=i-2

p指向第i个结点,while条件是j<i或j<=i-1

平均时间复杂度:

O(n)

注:插入和删除操作的完整过程包括查找操作,查找操作是O(n),而单个插入和删除操作只是移动指针,只是O(1)

**建立链表

一个辅助指针

头插法

平均时间复杂度:

O(n)

尾插法

两个辅助指针

平均时间复杂度:

O(n)

循环链表

循环链表合并

image-20220321200639831

时间复杂度:

O(1)

双向链表

image-20220321200840182

插入

4.不可以和1.或2.换

删除

不需要去找该删除结点的前驱结点

找第i个结点的时间复杂度:O(n)

下面只执行一次:O(n)

总结

双向循环链表是用空间换时间

结论:

p指向第i个结点前驱,while条件是j<i-1或j<=i-2

p指向第i个结点,while条件是j<i或j<=i-1

应用

2.1 顺序

2.2 链式

尾插法

空间复杂度:

O(1)

#include<stdio.h>
#include<stdlib.h>
#define LENGTH sizeof(struct node)
//定义一个节点
int len;//全局变量n
typedef struct node
{
	int Coffficient;
	int Exponent;
	struct node* next;
}*Pnode,Node;
//创建一个单链表(尾插法)
Pnode Create_List()
{
	Node * p,* tail, *head;
	int a,b;
	
	head = (Node*)malloc(LENGTH);//原型应为malloc(1*LENGTH),1省略
	tail = head;
	tail->next = NULL;
	printf("请输入结点个数:");
	scanf_s("%d", &len);
	printf("请输入元素,系数= , 指数=:\n");
	for (int i = 0; i < len; i++)
	{
		scanf_s("%d,%d", &a,&b);
			p = (Node*)malloc(LENGTH);
			p->Coffficient=a;
			p->Exponent = b;
			tail->next = p;
			p->next = NULL;
			tail = p;
	}
	return head;//f返回头结点
}
//按指数排序
void Sort_Linklist1(Node* phead) {//冒泡排序
	Node* p = phead->next;
	Node* q;
	int temp1,temp2, i=0;
	for (; i < len-1; i++, p = p->next) {
		for (q = p->next; q!= NULL; q = q->next) {

			if (p->Exponent < q->Exponent) {
				temp1 = p->Exponent;
				p->Exponent = q->Exponent;
				q->Exponent = temp1;
				temp2 = p->Coffficient;
				p->Coffficient = q->Coffficient;
				q->Coffficient = temp2;
			}
		}
	}	
}
//比较函数
int compare(int Exponent1, int Exponent2) {
	if (Exponent1 > Exponent2)
		return 1;
	if (Exponent1<Exponent2)
		return -1;
	if (Exponent1 = Exponent2)
		return 0;
}
//新生成
void Attach(int a, int b, Node** temp) {
	Node *p;
	p = (Node*)malloc(LENGTH);
	p->Coffficient = a;
	p->Exponent = b;
	p->next = NULL;
	(*temp)->next = p;
	*temp = p;
}
Pnode Add_List(Node* p1, Node* p2) {
	Node* front,*rear;
	p1 = p1->next;//从头结点的下一节点开始遍历
	p2 = p2->next;
	int sum;
	rear = (Node*)malloc(LENGTH);
	front = rear;
	while (p1 && p2) {
		switch (compare(p1->Exponent, p2->Exponent)) {
		case 1:
			Attach(p1->Coffficient, p1->Exponent, &rear);
			p1 = p1->next;
			break;
		case -1:
			Attach(p2->Coffficient, p2->Exponent, &rear);
			p2= p2->next;
			break;
		case 0:
			sum = p1->Coffficient + p2->Coffficient;
			Attach(sum, p2->Exponent, &rear);
			p1 = p1->next;
			p2 = p2->next;
			break;
		}
	}
	for (; p1; p1 = p1->next)//p2为空循环结束后继续遍历p1
		Attach(p1->Coffficient, p1->Exponent, &rear);
	for(;p2;p2=p2->next)//p1为空循环结束后继续遍历p2
		Attach(p2->Coffficient, p2->Exponent, &rear);
	rear->next = NULL;
	return front;
}

//遍历链表
void Print_List(Node* phead)
{
	Node* p = phead->next;//跳过头结点进行遍历
	while (p != NULL)//尾结点为空时终止(尾结点的指针域为空)
	{
		printf("%dX^%d\t", p->Coffficient,p->Exponent);
		p = p->next;
	}printf("\n");
}

int main()
{
	Node* s1,*s2,*s3;
	printf("请先创建链表\n");
	printf("输入Polynomial1");
	s1= Create_List();
	printf("指数从大到小排序后:\n");
	Sort_Linklist1(s1);
	Print_List(s1);
	printf("输入Polynomial2");
	s2= Create_List();
	Sort_Linklist1(s2);
	printf("指数从大到小排序后:\n");
	Print_List(s2);
	s3=Add_List(s1, s2);
	printf("多项式相加后:\n");
	Print_List(s3);
	return 0;
}

栈和队列

定义及特点

image-20220321201214918

栈:

image-20220321201251460

队:

image-20220308192212321

特点:

栈:后进先出

队列:先进先出

应用

image-20220321201258916

栈的表示和实现

数据类型定义

image-20220321201424640

SElemType是指元素类型

顺序栈

image-20220321201452647

image-20220321201503455

初始化

image-20220321201508074

判断是否为空及长度

image-20220321201522387

清空及释放

delete s.base 释放了数组的内存,但指针还是指向这块内存,只是这块内存不能被访问,所有将它们设为null

入栈

出栈

链表

初始化及是否为空

image-20220321201550212

image-20220321201554643

入栈、出栈及取栈顶

image-20220321201558930

image-20220321201606546

image-20220321201613037

**递归

见算法:递归

image-20220321201658440

缺点及转化

image-20220321201704401

image-20220321201711032

image-20220321201717186

image-20220321201721625

image-20220321201726793

队列的表示和实现

数据类型定义

image-20220321201732260

顺序队列

image-20220321201737270

front rear是表示指针,但不是指针变量,不是真正的指针

image-20220321201745921

image-20220321201752047

image-20220321201759999

image-20220321201805767

image-20220321201829500

初始化

image-20220321201838341

求队列长度

image-20220321201843798

入队

image-20220321201848805

出栈

image-20220321201854670

取队头元素

链队列

image-20220321201925417

初始化

image-20220321201931092

销毁

image-20220321201937209

入队

image-20220321201941741

image-20220321201956799

有头结点能把非空队列和空队列统一起来

出队

image-20220321202041736

取队头元素

image-20220321202109739

串、数组和广义表

image-20220321202117196

定义

image-20220321202130836

image-20220321202135973

image-20220321202142313

顺序存储

image-20220321202148219

image-20220321202200530

BF算法

image-20220321202206998

n为主串,m为子串

最好情况:O(m)

最坏情况:O(n*m)

?KMP算法

数组

image-20220321202233390

image-20220321202237924

image-20220321202250628

image-20220321202352561

顺序存储

image-20220321202443080

image-20220321202454769

image-20220321202502277

image-20220321202524490

image-20220321202533011

image-20220321202553260

特殊矩阵的压缩存储

image-20220321202705376

对称矩阵

a[i,j]的位置是[i(i-1)/2]+j-1

(为什么要减1:k从0开始存)

三角矩阵

注:下图公式都要-1

(为什么要减1:k从0开始存)

推导:

对角矩阵

image-20220316205920235

稀疏矩阵

image-20220316211426314

顺序表

image-20220316211521551

image-20220316211856285

十字链表

image-20220316212253238

image-20220316212600827

广义表

image-20220317193854480

image-20220317194012351

image-20220317194318063

性质

image-20220317194645822

image-20220317195547232

image-20220317201037492

运算

image-20220317201557298

posted @   Yancyxiao  阅读(101)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示