链表
单链表
单链表是由若干结点构成
单链表的结点只有一个指针域(单链表包含一个指针域和一个数据域)
链表的结构
头指针:指向第一个结点的地址
尾标志:终端结点的指针域为空
申请一个结点
typedef struct node
{
DataType data; //数据域
struct node *next; //指针域
}Node,*Link;
//用typedef去声明结构体时,Node和*Link两个位置就被定义成了类型
Node st; //struct node st;
Link p; //struct node *p; //p是一个指向结构体的指针
申请结点
p=(Link)malloc(sizeof(Node));
sizeof(node); //计算出node结点的大小
malloc(sizeof(Node)); //用malloc分配给Link这么大的空间 malloc返回函数时viod*
分配地址以后,其把首地址分配给了指针p,在使用这块空间的时候,需要对这块地址进行强制转换。转换成指针p希望看到的类型。
指针p是一个Link类型,所以把malloc也定义成Link类型
如何引用数据元素?
(*p).data;
p->data;
如何引用指针域?
p->next;
链表的实现
单链表的遍历操作
操作接口:void displayNode(Link head);
void displayNode(Link head)
{
p= head->next;
while(p!=NULL)
{
cout<<p->next<<endl;
p = p->next;
}
}
求单链表的元素个数
操作接口:int length(Link head);
int length(Link head){
p = head->next; //p指向头指针的next域
count = 0; //count的数值为零
while(p!=NULL)
{
p = p->next; //如果p不为空,则p指向下一个结点的 // next域
count++;
}
return count; //注意count和初始化返回值之间的关系
}
单链表的查找操作
int queryNode(Link head,DaraType x){
p = head->next;
count = 0;
while(p!=NULL)
{
if(p—>data==x)
{
cout<<data<<endl; //找到则调用输出函数,并提 //前返回true
return true;
}
p = p->next;
}
//如果链表结束,说明没有找到
return false;
}
单链表的插入操作
操作接口:void insertNode(Link head,int i,DataType x);
node = (Link)malloc(sizeof(Node)); //申请一个结点node
node->data = x; //结点的数据域是x
node -> next = p->next; //p的next域赋给node的 //next域
p->next = node; //将node的数据域赋值给p的next域
-
工作指针p初始化
-
查找第i-1个结点并使用、工作指针p指向该结点
-
若查找不成功,则返回false
3.1生成一个元素值为x的新结点;
3.2将新结点s插入到结点p之后;
3.3返回true;
bool insertNode(Link head,int i,DataType x)
{
p = head; //工作指针p指向头结点
count = 0;
while (p!=NULL&&count<i-1) //查找第i-1个结点
{
p=p->next;
count++;
}
if(p==NULL)
return false; //没有找到第i-1个结点
else{
node = (Link)malloc(sizeof(Node));//申请一个结点 //node
node->data=x;
node->next=p->next; //结点node插入结点p之后
p->next=node;
return ture;
}
}
创建一个单链表—头插法
操作接口:Link newList(DataType a[],int n)
头插法:将待插入结点插在头结点的后面。
初始化头结点
head = (Link)malloc(sizeof(Node));
head->next=NULL;
插入第一个元素
node = (Link)malloc(sizeof(Node));
node->data=a[0];
node->next=head->next;
head->next=node;
node = (Link)malloc(sizeof(Node));
node->data=a[1];
node->next=head->next;
head->next=node;
template <class DataType>
Link newList(DataType a[],int n)
{
head=(Link)malloc(sizeof(Node));
head->next=NULL;
//创建后续结点
for(i = 0; i < n;i++)
{
node = (Link)malloc(sizeof(Node));
node->data = a[i];
node->next = head->next;
head->next = node;
}
return head;
}
创建一个单链表—尾插法
操作接口:Link newList(DataType a[],int n)
尾插法:将待插入结点插在终端结点的后面
head = (Link)malloc(sizeof(Node)); //创建一个头
head->next = NULL;
rear = head; //将head赋给rear
插入第一个元素结点
node = (Link)malloc(sizeof(Node)); //创建结点node
node->data = a[0]; //结点第一个数据域
rear->next = node; //rear的next域是node
rear = node; //将node名为rear
依次插入每一个结点
node = (Link)malloc(sizeof(Node))
node->dat = a[1];
rear->next = node;
rear = node;
尾插法
Link newList(DataType a[],int n)
{
head = (Link)malloc(sizeof(Node));
head->next = NULL;
rear = head; //尾指针初始化
for(i = 0; i<n;i++)
{
node=(Link)malloc(sizeof(Node));//创建结点
node->data = a[i];
rear->next = node;
rear = ndoe;
}
rear->next = NULL;
return head;
}
单链表结点的删除
操作接口:bool deleteNode(Link head, Datatype x);
q->next = p->next;
free(p);
将q的next域指向p的next域,将被删除的p空间释放。
查找结点
在查找过程中,如果发现p所指向的结点data值不是要找的x,则p,q同时后移;一旦找到则执行删除操作
查找到p结点并将其删除
1.如何找到p结点。
2.如何保证p,q指针一前一后。
初始化
p = head->next;
q = head;
指针移动一次
q = p;
p = p->next;
删除中的特殊情况
在查找过程中,如果一直没有找到data域为x的结点,或者发现待删除的表是空表,则提前返回false
if(head==NULL||head->next==NULL){
return false;
}
单链表的删除
1.判断是否是空表,如果是空表返回false;
2.工作指针p,q初始化
3.若p指针不为空,则继续下列循环:
3.1如果找到data域等于x的结点,则:
3.1.1摘链,将结点p的从链表上摘下来
3.1.2释放别删除的结点
3.1.3提前返回true,代表删除成功
4.循环结束了,说明没有找到和x相等的结点,则返回false
bool deleteNode(Link head,DataType x){
if(head==NULL||head->next==NULL){
return false;
}
p=head->next;
q=head;
while(p!=NULL){
if(p->data==x){
q->next=p->next;
free(p); //单链表的释放
return true;
}
else{
q = p;
p = p->next;
}
}
//如果循环结束了,说明没有找到和x相关的结点
return false;
}
循环列表的实现
将单链表的首位相接,将终端结点的指针由空指针改为指向头结点,构成单循环链表,简称循环链表
循环链表的插入
node = (Link)malloc(sizeof(Node));
node->data = x;
node->next = p->next;
p->next = node;
p! = NULL; //p != head
p->next != NULL; //p->next != head
双向链表
在单链表的每一个结点中再设置一个指向其前驱结点的指针域。
data:数据域,储存数据元素
prior:指针域,储存该结点的前驱结点地址
next:指针域,储存该结点的后继结点地址