1.链表的概念
线性表是一类很常用的数据结构,分为顺序表和链表。
其中顺序表可以简单地理解为“数组”这个概念,定义一个数组,计算机会从内存中取出一块连续的地址来存放给定长度的数组。而链表与数组不同的地方在于,链表是由若干个结点组成,且结点在内存中的存储位置通常是不连续的。
链表的结点一般由两个部分组成,数据域和指针域。
struct node{
typename data;
node* next;
};
以链表是否存在头结点,又可以把链表分为带头结点的链表和不带头结点的链表。头结点一般称为head,且其数据域data不存放任何内容,而指针域next指向第一个结点(数据域有内容)。最后一个结点的指针指向NULL。
(1)使用new运算符为链表结点分配空间
new是C++中用来申请动态空间的运算符,其返回内型同样是申请的同变量类型的指针。
typename* p = new typename;
如果申请失败,会启动C++异常机制处理。
(3)内存泄露
内存泄露是指使用malloc与new开辟出来的内存空间在使用过后没有释放,导致其在程序结束之前始终占据该内存空间,这是一些较大的程序中很容易导致内存消耗过快以致最后无内存可分配。
释放用new和malloc开辟出来的空间:
使用delete运算符
delete(p);
释放指针变量p所指向的内存空间;将指针变量p指向空地址NULL。
(4)链表的基本操作
①创建链表
node* create(int Array[]){
node *p,*pre,*head;
head = new node;
head->next = NULL;
pre = head;
for(int i = 0;i<Array.size();i++){
p = new node;
p->next = NULL;
p->data = Array[i];
pre->next = p;
pre = p;
}
return head;
}
(3)插入元素
插入元素是指在链表给定位置的地方插入一个结点。
//将x插入到第pos个结点
void insert(node* head,int pos,int x){
node* p = head;
for(int i = 0;i<pos-1;i++){//此处pos-1是为了将指针指到pos的前一个结点,不是因为head结点
p = p->next;
}
node* q = new node;
p->data = x;
q->next = p->next;
p-<next = q;
}
(4)删除元素
删除元素是指删除链表上所有值为x结点。
//将x插入到第pos个结点
void del(node* head,int x){
node* p = head->next;
node* pre = head;
while(p!=NULL){
if(p->data == x){
pre->next = p->next;
delete(p);
p = pre->next;
}
else
{
pre = p;
p=p->next;
}
}
}
2.静态链表
静态链表的实现原理是hash,即通过建立一个结构体数组,并令数组的下标直接表示结点的地址,来达到直接访问数组中的元素就能访问结点的效果。静态链表不需要头结点。
(1)定义
struct Node{
typename data;
int next;
}node[size];
next用来存放下一个结点的地址,实际上就是数组下标。尾节点next为-1。
在使用静态链表时,尽量不要把结构体类型名和结构体变量名取相同的名字。