单链表的各种基本运算
文章目录
- 前言
- 一,头插法,与尾插法
- 二,各种基本运算
- 三,代码展示
- 总结
前言
链表是一种通用的数据结构,是用一组任意的存储单元存放线性表的元素,这组存储单元可以是连续的也可以不连续,甚至可以零散分布在内存中的任意位置。为了能正确表示元素之间的逻辑关系,每个存储单元在存储数据元素的同时,还必须存储其后继元素所在的地址信息,这个地址信息称为指针,这两部分元素组成了数据元素的存储映像,称为结点(Node)。 本实训项目的主要内容是基于C语言开发一个具有基本功能的单链表。
一、单链表的头插法和尾插法
设给定的数组元素存放在数组a[n]中,建立单链表就是生成存储这n个数据元素的单链表。有两种建立方法:头插法和尾插法。 尾插法的基本思想是每次将新申请的结点插在终端结点的后面,见下图
尾插法的步骤为: 1.初始化一个带头结点的空链表,并领头指针first及尾指针r指向头结点,如上图所示。 2.用循环依次在尾指针所指结点后面插入值为a[i]的新建结点,(i>=0&&i<n) 3.置最后一个结点的指针域为NULL 4.返回指向头结点的指针
代码如下
void CreateLisetF( LinkNdoe *&L,ElemType a[], int n ){ //采用头插法
LinkNdoe * s; //用来操作
L=(LinkNdoe *)malloc( sizeof(LinkNdoe ));//创建头节点
L->next=NULL;
for(int i=0;i<n;i++){
s=(LinkNdoe *)malloc(sizeof(LinkNdoe));//创建新节点
s->data=a[i];
s->next=L->next;//将节点S插在原节点之前,头结点之后
L->next=s;
}
}
void CreateListR(LinkNdoe *&L,ElemType a[],int n){//采用尾插法
LinkNdoe *r,*s;
L=(LinkNdoe*)malloc(sizeof(LinkNdoe)); //创建头结点
L->next=NULL;
r=L;
for(int i=0;i<n;i++){
s=(LinkNdoe*)malloc(sizeof(LinkNdoe));
s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;//尾结点NEXT为空
}
二、各种基本运算
1,建立结构
代码如下(示例):
typedef struct LNode
{
ElemType data; //
struct LNode *next; //指向后继节点
}LinkNdoe;//声明单链表节点类型
2.各种基本运算
(1),初始化单链表
void InitList(LinkNdoe *&L){ //初始化线性表
L=(LinkNdoe *)malloc(sizeof(LinkNdoe)); //创建头结点
L->next=NULL;//将单链表置为空表
}
(2),销毁单链表
void DestoryList(LinkNdoe *&L){//销毁单链表
LinkNdoe *pre=L,*p=pre->next;
while (p!=NULL)
{
free(pre);
pre=p;
p=p->next; //pre p 同步往后移
}
}
(3),判断单链表是否为空表
bool ListEmpty(LinkNdoe *L){ //判断链表是否为空表
return(L->next==NULL);
}
(4),输出单链表
int ListLength(LinkNdoe *L){ //求单链表的长度
int i=0;
LinkNdoe *p=L;
while (p->next!=NULL)
{
i++;
p=p->next;
}
return i;
}
(5),求单链表的第i个元素
void DispList(LinkNdoe *L){ //输出线性表
LinkNdoe *p=L->next; //p指向首节点
while (p!=NULL)
{
printf(" %c",p->data);
p=p->next;
}
printf("\n");
}
(6),查找第一个值域为e的值
bool GetElem(LinkNdoe *L,int i,ElemType& e){//求线性表的第i个元素
int j=0;
LinkNdoe *p=L;//指向头结点
if(i<0){
return false;
}
while (j<i&&p!=NULL)
{
j++;
p=p->next;
}
if(p==NULL){
return false;
}else
{ e=p->data;
return true;
}
}
(7),插入第i个元素
bool ListInsert(LinkNdoe *&L,int i,ElemType e) //插入第i个元素
{ int j=0;
LinkNdoe *p=L,*s;
if(i<=0){
return false;
}
while (j<i-1&&p->next!=NULL)
{
j++;
p=p->next;
}
if(p==NULL){
return false;
}else{
s=(LinkNdoe*)malloc(sizeof(LinkNdoe));
s->data =e;
s->next=p->next;
p->next =s;
return true;
}
}
(8),删除第i个值
bool ListDelete(LinkNdoe *&L,int i,ElemType e){//删除第i个值
int j=0;
LinkNdoe *p=L,*q;
if(i<=0){
return false;
}
while (j<i-1&&p->next!=NULL)
{
/* code */
j++;
p=p->next;
}
if(p==NULL){
return false;
}else{
q=p->next;
if(q==NULL){
return false;
}
e=q->data;
p->next=q->next;
free(q);
return true;
}
}
所有代码展示
#include <stdio.h>
#include<malloc.h>
typedef char ElemType;
typedef struct LNode
{
ElemType data; //
struct LNode *next; //指向后继节点
}LinkNdoe;//声明单链表节点类型
void CreateLisetF( LinkNdoe *&L,ElemType a[], int n ){ //采用头插法
LinkNdoe * s; //用来操作
L=(LinkNdoe *)malloc( sizeof(LinkNdoe ));//创建头节点
L->next=NULL;
for(int i=0;i<n;i++){
s=(LinkNdoe *)malloc(sizeof(LinkNdoe));//创建新节点
s->data=a[i];
s->next=L->next;//将节点S插在原节点之前,头结点之后
L->next=s;
}
}
void CreateListR(LinkNdoe *&L,ElemType a[],int n){//采用尾插法
LinkNdoe *r,*s;
L=(LinkNdoe*)malloc(sizeof(LinkNdoe)); //创建头结点
L->next=NULL;
r=L;
for(int i=0;i<n;i++){
s=(LinkNdoe*)malloc(sizeof(LinkNdoe));
s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;//尾结点NEXT为空
}
void InitList(LinkNdoe *&L){ //初始化线性表
L=(LinkNdoe *)malloc(sizeof(LinkNdoe)); //创建头结点
L->next=NULL;//将单链表置为空表
}
void DestoryList(LinkNdoe *&L){//销毁单链表
LinkNdoe *pre=L,*p=pre->next;
while (p!=NULL)
{
free(pre);
pre=p;
p=p->next; //pre p 同步往后移
}
}
bool ListEmpty(LinkNdoe *L){ //判断链表是否为空表
return(L->next==NULL);
}
int ListLength(LinkNdoe *L){ //求单链表的长度
int i=0;
LinkNdoe *p=L;
while (p->next!=NULL)
{
i++;
p=p->next;
}
return i;
}
void DispList(LinkNdoe *L){ //输出线性表
LinkNdoe *p=L->next; //p指向首节点
while (p!=NULL)
{
printf(" %c",p->data);
p=p->next;
}
printf("\n");
}
bool GetElem(LinkNdoe *L,int i,ElemType& e){//求线性表的第i个元素
int j=0;
LinkNdoe *p=L;//指向头结点
if(i<0){
return false;
}
while (j<i&&p!=NULL)
{
j++;
p=p->next;
}
if(p==NULL){
return false;
}else
{ e=p->data;
return true;
}
}
int LocateElem(LinkNdoe *L,ElemType e){ //查找第一个值域为e的值
int i=1;
LinkNdoe *p=L->next;//p指向首节点
while (p!=NULL&&p->data!=e)
{
p=p->next;
i++;
}
if(p==NULL){
return false;
}else
{
return i;
}
}
bool ListInsert(LinkNdoe *&L,int i,ElemType e) //插入第i个元素
{ int j=0;
LinkNdoe *p=L,*s;
if(i<=0){
return false;
}
while (j<i-1&&p->next!=NULL)
{
j++;
p=p->next;
}
if(p==NULL){
return false;
}else{
s=(LinkNdoe*)malloc(sizeof(LinkNdoe));
s->data =e;
s->next=p->next;
p->next =s;
return true;
}
}
bool ListDelete(LinkNdoe *&L,int i,ElemType e){//删除第i个值
int j=0;
LinkNdoe *p=L,*q;
if(i<=0){
return false;
}
while (j<i-1&&p->next!=NULL)
{
/* code */
j++;
p=p->next;
}
if(p==NULL){
return false;
}else{
q=p->next;
if(q==NULL){
return false;
}
e=q->data;
p->next=q->next;
free(q);
return true;
}
}
int main(){
LinkNdoe *h;
ElemType e;
printf("单链表的基本运算如下:\n");
printf(" (1)初始化单链表h\n");
InitList(h);
printf(" (2)依次采用尾插法插入a,b,c,d,e元素\n");
ListInsert(h,1,'a');
ListInsert(h,2,'b');
ListInsert(h,3,'c');
ListInsert(h,4,'d');
ListInsert(h,5,'e');
printf(" (3)输出单链h:");
DispList(h);
printf(" (4)单链表h的长度:%d\n",ListLength(h));
printf( " (5)单链表h为%s\n",(ListEmpty(h))?"空":"非空");
GetElem(h,3,e);
printf(" (6)单链表h中第3个元素:%c\n",e);
printf(" (7)元素a的位置:%d\n",LocateElem(h,'a'));
printf(" (8)在第4个位置插入f元素\n");
ListInsert(h,4,'f');
printf(" (10)删除h上的第3个元素\n");
ListDelete(h,3,e);
printf(" (11)输出单链表h:\n");
DispList(h);
printf(" (12)释放单链表h\n");
DestoryList(h);
return 0;
}
总结
单链表是学习数据结构中,必须学习的重要知识。