单链表的创建算法
本文根据:清华大学出版社《数据结构与算法(C语言版)(第3版)》整理,详细请见书本。
当一个序列中只含有指向它的后继结点的链接时,就称该链表为单链表。
单链表的示意图如下:
Head指针为单链表的头指针,单链表L:L既是单链表的名字,也是其头指针。链表中的最后一个结点的指针域定义为空指针(NULL)。
单链表的定义:
struct Node
{
ElemType data;
struct Node *next;
};
typedef struct Node LNode;
typedef struct Node *LinkedList;
单链表有带头结点和不带头结点之分。
上图为没有头结点的单链表,下图为带有头结点的单链表:
//不带头结点的单链表的初始化
void LinkedListInit1(LinkedList L)
{
L=NULL;
}
//带头结点的单链表的初始化
void LinkedListInit2(LinkedList L)
{
L=(LNode *)malloc(sizeof(LNode));
if(L==NULL)
{
printf("申请空间失败!");
exit(0);
}
L->next=NULL;
}
//带头结点的单链表求表长
int LinkedListLength(LinkedList L)
{
LNode *p; //p需要声明为LNode类型
p=L->next;
int j=0;
while(p!=NULL)
{
j++;
p=p->next; //将p向下移动一个结点
}
return j;
}
//带头结点的单链表取元素操作
LinkedList LinkedListGetINode(LinkedList L, int i)
{
LNode *p;
p=L->next;
int j=1;
while((p!=NULL)&&(jnext;
j++;
}
return p;
}
//带头结点的单链表定位操作
LNode LinkedListLocateE(LinkedList L, ElemType e)
{
LNode *p;
p=L->next;
while((p!=NULL)&&(p->data!=e))
{
p=p->next;
}
return p;
}
2)在链表的中间插入
(1)创建一个新的结点q。
(2)将此结点的数据域赋值为e,并将它的next指针指向p。
(3)查找到p的前驱结点pre。
(4)将pre的next指针指向新创建的结点q。
操作示意图如下:
//不带头结点的单链表的插入操作
void LinkedListInertQE1(LinkedList L, LinkedList p, ElemType e)
{
q=(LNode *)malloc(sizeof(LNode)); //创建一个新的结点q
if(q==NULL)
{
printf("申请空间失败!");
exit(0);
}
q->data=e;
if(p==L) //在表头插入
{
q->next=L;
L=q;
}
else //在表的中间进行插入
{
pre=L;
while((pre!=NULL)&&(pre->next!=p)) //寻找p的前驱
pre=pre->next;
q->next=pre->next;
pre->next=q;
}
}
//带头结点的单链表的插入操作
void LinkedListInertQE2(LinkedList L, LinkedList p, ElemType e)
{
q=(LNode *)malloc(sizeof(LNode)); //创建一个新的结点q
if(q==NULL)
{
printf("申请空间失败!");
exit(0);
}
q->data=e;
//插入新的结点
pre=L;
while((pre!=NULL)&&(pre->next!=p)) //寻找p的前驱
pre=pre->next;
q->next=pre->next;
pre->next=q;
}
2)p是链表中的其他结点
(1)找到p的前驱结点pre。
(2)将pre->next指向p->next。
(3)释放p。
示意图如下:
//不带头结点的单链表的删除操作
void LinkedListDeleteQE1(LinkedList L, LinkedList p, ElemType e)
{
pre=L;
while((pre!=NULL)&&(pre->next->data!=e)) //查找元素e的前驱
pre=pre->next;
p=pre->next;
if(p!=NULL) //找到需要删除的结点
{
if(p==L) //删除的是第一个结点
L=p->next;
else //删除的是其他结点
pre->next=p->next;
free(p);
}
}
//带头结点的单链表的删除操作
void LinkedListDeleteQE2(LinkedList L, LinkedList p, ElemType e)
{
pre=L;
while((pre!=NULL)&&(pre->next->data!=e)) //查找元素e的前驱
pre=pre->next;
p=pre->next;
if(p!=NULL) //找到需要删除的结点
{
pre->next=p->next;
free(p);
}
}
//用头插法创建带头结点的单链表
void LinkedListCreateHeadL(LinkedList L, ElemType a[n])
{
L=(LNode *)malloc(sizeof(LNode));
if(L==NULL)
{
printf("申请空间失败!");
exit(0);
}
L->next=NULL;
for(i=0; idata=a[i];
p->next=L->next;
L->next=p;
}
}
//用尾插法创建带头结点的单链表
void LinkedListCreateTailL(LinkedList L, ElemType a[n])
{
L=(LNode *)malloc(sizeof(LNode));
if(L==NULL)
{
printf("申请空间失败!");
exit(0);
}
L->next=NULL;
tail=L; //设置尾指针,方便插入
for(j=0; jdata=a[j];
p->next=NULL;
tail->next=p;
tail=p;
}
}
//带头结点的单链表合并操作
void LinkedListMergeLaLb(LinkedList La, LinkedList Lb, LinkedList Lc)
{
pa=La->next;
pb=Lb->next;
Lc=La; //借用表La的头结点作为表Lc的头结点
pc=Lc;
while((pa!=NULL)&&(pb!=NULL))
{
if(pa->data<=pb->data)
{
pc->next=pa;
pc=pa;
pa=pa->next;
}
else
{
pc->next=pb;
pc=pb;
pb=pb->next;
}
}
if(pa!=NULL)
pc=pa->next;
else
pc=pb->next;
free(pb); //将Lb的表头结点释放
}
程序实例:尾插法创建单链表
首先在VS2010中新建Win32 控制台应用程序的项目LinkedList,结果如下:
LinkedList.cpp : 定义控制台应用程序的入口点。
// LinkedList.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include
#include
typedef struct node
{
int data;
struct node *next;
}*LinkedList;
LinkedList LinkedListCreateTailL(int a[8])
{
LinkedList p, L, tail;
int i=0;
L=(struct node*)malloc(sizeof(struct node));
tail=L;
for(i=0; i<8; i++)
{
p=(struct node*)malloc(sizeof(struct node));
p->data=a[i];
tail->next=p;
tail=p;
}
tail->next=NULL;
return L;
}
void LinkedListPrint(LinkedList L)
{
LinkedList p;
p=L->next;
while(p!=NULL)
{
printf("%d ",p->data);
p=p->next;
}
}
void main()
{
int a[8], i;
LinkedList L;
printf("请输入8个列表元素,以回车结束:\n");
for(i=0; i<8; i++)
{
scanf("%d", &a[i]);
}
L=LinkedListCreateTailL(a);
LinkedListPrint(L);
}
Ctrl+F5执行以上cpp文件,程序运行截图: