栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

《算法笔记》读书记录DAY

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

《算法笔记》读书记录DAY

CHAPTER_7  提高篇(1)——数据结构(1)

 7.3.1链表的概念

线性表是一种很常用的数据结构,它是n个相同特性的元素组成的序列,分为顺序表和链表。其中顺序表我们可以简单地理解成“数组”的概念,它是一块连续的地址来存储给定长度的表结构。而链表则是由若干个结点组成(每个结点代表一个元素),它们在内存中并不是连续在一起存储的,因此每个结点内含有一个指针指向下一个元素。

我们可以用结构体表示链表:

struct node {
	type date;     //type表示元素的类型,例如int或者char 
	node* next;
};

每一个结点都有一个指针next,指向下一个结点的位置,这样就像串链子一样形成一个线性结构。需要注意的是,第一个结点通常不存放数据,我们将其称作头结点(head),它标志着一个链表的开始。同样地,最后一个结点的指针next的值为空,它标志着链表的结束。

 

 7.3.2为链表结点分配内存空间

上一节我们已经了解了链表结点的定义,这节我们介绍如何在每次使用新结点时分配相应的内存  空间。关于内存的申请和释放,我们使用C++的new和delete关键字。

new运算符

new是用来申请动态空间的运算符,其返回类型是申请的同变量类型的指针,其基本用法如下:

typename* p=new typename;

例如申请一个int型变量和一个node型变量:

int* p=new int;
node* p=new node;

有一点要注意,申请空间有可能失败,当失败时会启动C++异常机制处理,在没有特殊处理的情况下会退出程序。不过,一般正常分配一个结点空间,是不会失败的。

delete运算符

delete运算符与new成对使用,当我们用指针p申请了一个对应的空间,在使用完毕后切记使用delete将空间释放,否则容易产生内存泄露。

node* p=new node;
delete(p);        //释放内存

 7.3.3链表的基本操作

链表的创建

我们已经能够创建零散的结点了,接下来要做的是把这些结点连接成链表。方法也很简单,用for循环来把每个结点的next指向下一个即可。例如下面存储int型数据的链表。

typedef struct Node {
	int date;
	node *next;
}node;

node* create(int array[],int n) {     //array为需要加入链表的数据,n为数据个数  
	node *p, *pre, *head;             //pre记录当前结点的前一个结点,head为头结点
	head=new node;
	head->next=NULL;                  //头结点的指针域初始化为空 
	pre=head;                         //前驱结点初始化为第一个结点
	for(int i=0;idata=array[i];             //赋值 
		p->next=NULL;                 //指针域设为空,在下面的步骤中将其放在链表最后面
		pre->next=p;                  //将p连接之最后 
		pre=p;                        //pre记录最后一个结点的前一个 
	}
	return head;
}

查找元素

我们如何在链表中查找是否有某元素x呢?其实也很简单,我们设立一个计数器count并将其初始化为0,然后从头结点开始遍历链表,依次判断当前结点的date是否等于x,如果相等则令count++。

int search(node* head,int x) {
	int count=0;
	node *p=head->next;        //从第一个结点开始
	while(p) {
		if(p->data==x)
			count++;
		p=p->next;
	} 
	return count;
}

插入元素

我们先明确链表插入的定义:我们在链表的第i个位置x,是指在不包括头结点的情况下,插入完成后使第i个元素成为x。例如1 2 3 4,我们要在第3个位置插入5,那么插入结果为1 2 5 3 4。

我们要在第i个位置插入结点p,要找到第i个位置的前一个结点pre,例如要在第1个位置插入要找到头结点,在第3个位置插入要找到第二个结点(头结点不计入)的位置。找到前一个结点pre后,用临时指针tmp存储pre->next,然后令pre->next=p,p->next=tmp,这样就完成了结点的插入。如下图

void insert(node* head,int pos,int x) {
	node *p=new node, *pre=head, *tmp;
	p->data=x;
	for(int i=0;inext;               
	}
	tmp=pre->next;
	pre->next=p;
	p->next=tmp;
}

删除元素

对链表来说,删除元素x是指删除链表上所有值为x的结点。删除结点与插入类似,需要一个pre指针来指向欲删除结点p的前一个结点,令pre->next=p->next,delete(p)即可。

void del(node* head, int x) {
	node *p=head->next, *pre;
	while(p) {                  //从头结点后一个开始遍历,pre始终指向p前一个结点 
		if(p->data==x) {
			pre->next=p->next;
			delete(p);
		}
		p=p->next;
		pre=pre->next;
	}
}

 

上面介绍了单链表的简单原理。而C++在STL中也有链表相关容器list,它是一个双向链表。使用方法可以参考博客 C++中list用法详解_Donny's Blog-CSDN博客_c++list 。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/317156.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号