数据结构学习Day1

数据结构学习Day1

前言

作为一名和CS基本差不多的AI专业学生,掌握扎实的计算机基本知识是非常必要的。虽然是大一,但是为了赶超别人并且提前准备就业或者考研,数据结构的学习自然提上日程。之前只是零散的接收数据结构的知识,单独发系列文章记录自己的系统性学习过程,为了激励自己也为了方便复盘,尽可能用明白的语言记录自己的心得,不当之处希望各位大佬批评指正。

本人笔记以C语言为主,若翻看笔记的话要有C或者C++基础

参考资料

清华大学 严蔚敏《数据结构(C语言版)》

王道考研 数据结构 20年版

B站蓝桥杯系列算法课程

线性表

入门级别的数据结构学习,线性结构。顾名思义,就是n个数据元素的有限的有序排列。

顺序表

顺序表是线性表的一个最简单的体现,个人看来类似于数组(王道的课程里面也是数组)

比如,利用结构体创建一个顺序表,最大长度是静态数组的长度,length代表能使用的长度

typedef struct{
	int data[10];
	int length;
} SqList;

对顺序表进行初始化,就是遍历赋值,并把可使用长度设置到最大长度,注意函数参数

void InitList(SqList &l){
	for(int i=0;i<10;++i){
		l.data[i]=i;
	}
	l.length=10;
}

输出顺序表

void PrintList(SqList l){
	for(int i=0;i<l.length;++i){
		cout<<l.data[i]<<endl;
	}
}

延长顺序表,无非就是涉及到动态的内存申请和释放,在C语言中是malloc和free函数,写惯了C++的new和delete一开始有点不适应

void Extend(SqList &l, int lengthExtend){
	int *p=l.data;
	l.data = (int *)malloc((l.Maxlength+lengthExtend)*sizeof(int));
	for(int i=0;i<l.Maxlength ;++i){
		l.data[i]=p[i];
	}
	l.Maxlength =l.Maxlength +lengthExtend;
	free(p);
}

顺序表的查和改无非就是遍历查找或者排序后二分查找,不做赘述

单向链表

链表在C++课程中已经接触过,先学习单向链表

作为任何数据结构,最基本的功能就是增删查改

作为单向链表,他在内存中的组成可以认为是两块区域,一个用来存放数据部分,一个用来存放指向下一个节点的指针

可以采用下列结构体

typedef struct LNode{
	int data;
	struct LNode *next;
}LNode,*LinkList;

typedef不做赘述,定义了一个结构体,一个结构体指针,其中结构体指针是用来做表头,单独列出来意义更加明确

插入新节点

函数参数为链表头部,插入的位置,元素数值

bool Insert(LinkList &l,int i,int e){
	if(i<1){
		return false;
	}
	LNode *p; //扫描用指针 
	int j;//第几个节点
	p=l;//让扫描节点指向头部
	//下面是扫描节点,认为头节点是空的,为第0个,扫描到插入位置之前的那一个节点
	while(p!=NULL&&j<i-1){
		p=p->next ;
		++j;
	} 
	if(p==NULL){
		return false;
	}
	LNode *s=(LNode *)malloc(sizeof(LNode));//申请新节点 
	s->data=e;
	s->next=p->next ;//别和下一句写倒了,这是创建上一个节点和下一个节点链接的两句话 
	p->next =s;//同上 
	return true;
}//对于没有头结点的,直接找到i-1个节点或者直接创建一个(指在头部插入),接下来都会了吧 

前插节点

可以采取后插节点复制前一个节点的方法,从而不必知道表头的地址

bool InsertPriorSimple(LNode *n,int e){
	LNode *s=(LNode *)malloc(sizeof(LNode));
	s->data =n->data ;
	s->next =n->next ;
	n->next =s;
	n->data =e;
	return true;
} 

删除节点(非最后一个节点)

就是复制下一个节点的数据,删除下一个节点,要不然数据就断了

bool DeletNode(LNode *n){
	LNode *q=n->next;
	n->data =n->next->data;
	n->next =q->next;
	free(q);
	return true;
}

如果是最后一个节点呢?很明显找不到前一个节点的next数据,删不干净,单向链表的弊端显现出来了

单链表的查找-按位查找

稍作改动就可以,把i-1改为i

while(p!=NULL&&j<i){
		p=p->next ;
		++j;
} 

之后return p,即要找的节点

单链表的查找-按值查找

外界传入一个指定的e的值,从链表中查找

while(p!=NULL&&p->data!=e){
		p=p->next ;
		++j;
}

之后return p,即要找的节点

单链表的建立

主要分为头插法和尾插法

头插法

书上给的方法是这样的

void Initial(LinkList &L,int n){
	int t;
	L=(LinkList)malloc(sizeof(LNode));
	L->next =NULL;
	for(int i=n;i>0;--i){
		p=(LNode *)malloc(sizeof(LNode));
		cin>>t;
		p->data=t;
		p->next=L->next ;
		L->next =p;
	}
}

很明显

p->next=L->next ;
L->next =p;

这两句就是倒着插入新节点

尾插法

尾插法可以遍历链表,找到p->next为NULL的节点,调用插入下一个的函数

不过这样循环会越来越慢,时间复杂度为O(n^2)

可以借鉴头插的思路,设置一个尾部指针,调用插入函数

你可能感兴趣的:(数据结构学习,数据结构,c++,链表)