线性表是一类常用的数据结构,分为顺序表和链表
顺序表可以简单理解为数组的概念
按正常方式定义一个数组时,计算机会从内存中取出一块连续的地址来存放给定长度的数组
而链表则使由若干个结点组成
每个结点代表一个元素
而结点在内存中的存储位置通常是不连续的
struct node{
typename data;
node* next;
};
链表分为带头结点的点和不带头结点的点
头结点一般称为head,且数据域data不存放任何内容
而指针域next指向第一个数据域有内容的结点
1、使用malloc函数或new运算符为链表结点分配内存空间
①malloc函数
是c语言stdlib.h头文件下用于申请动态内存的函数
其函数类型是申请的同变量类型的指针
基本类型:
int * p=(int*)malloc(sizeof(int))
这个写法的逻辑是:
以需要申请的内存空间大小(sizeof(node))为malloc函数的参数
这样malloc函数就会向内存申请一块大小为sizeof(node)的空间
并且返回指向这块空间的指针
但是这个指针此时是一个未确定类型的指针*void
因此需要强制转换(int*)
赋值等号
【申请失败】返回NULL
失败一般发生在使用malloc申请了较大的动态数组
②new运算符
c++用来申请动态空间
其返回类型同样是申请的同变量类型的指针
int* p=new int;
如果申请失败,会启动c++异常机制处理而不是返回空指针NULL
失败原因同上
2、内存泄露
指的是使用malloc与new开辟出来的内存空间在使用过后没有释放
导致其在程序结束之前始终占据该内存空间
在一些较大程序中很容易导致内存消耗过快以致最后无内存分配
①free函数
对应malloc函数(头文件stdlib.h)
free(p)
free两个效果:
a:释放指针变量p指向的内存空间
b:将指针变量p指向空地址NULL
②delete运算符
对应new
delete(p);
3、链表的基本操作
①创建链表
把每个结点的next指针指向下一个结点的地址即可
一般使用for循环来建立需要的链表
#include<utility>
#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
struct node{
int data;
node* next;
};
node* create(int Array[])
{
node *p,*pre,*head;
head=new node;
head->next=NULL;
pre=head;
for(int i=0;i<5;i++)
{
p=new node;
p->data=Array[i];
p->next=NULL;
pre->next=p;
pre=p;
}
return head;
}
int main()
{
int Array[5]={5,3,6,1,2};
node* L=create(Array);
L=L->next;//从第一个结点开时有数据域
while(L!=NULL)
{
printf("%d",L->data);
L=L->next;
}
return 0;
}
②查找元素
③插入元素
void insert(head* head,int pos,int x)
{
node* p=head;
for(int i=0;i<pos-1;i++)
{
p=p->next;
}
node* q=new node;
q->data=x;
q->next=p->next;
p->next=q;
}
④删除元素
void del(head* head,int x)
{
node* p=head->next;
node*pre=head;
while(p!=NULL)
{
if(p->data==x)
{
pre->next=p->next;
delete(p);
p=p->next;
}
else
{
pre=p;
p=p->next;
}
}
}
4、静态链表
动态链表需要指针来建立结点之间的连接关系
对有些问题来说,结点的地址都是比较小的整数
就没有必要去建立动态链表
而应该使用静态链表
静态链表的实现原理是hash
即通过建立一个结构体数组
并令数组的下标直接表示结点的地址
来达到直接访问数组中的元素就能访问结点的效果
另外
由于结点的访问非常方便
因此静态链表是不需要头结点的
struct Node{
typename data;
int next;
}node[size];
next用以存放下一个结点的地址(事实上就是数组下标)
【注意】
在使用静态链表时,尽量不要把结构体类型名和结构体变量名取成相同的名字
知识点来自于《算法笔记》