其结点在存储器中的位置是随意的,即逻辑上相邻的数据元素在物理上不一定相邻。
通过指针来实现,每个存储结点都包含两部分:数据域和指针域。
数据域:存储元素数值数据。
指针域:存储直接后继或者直接前驱的存储位置。
注:牺牲空间效率换取时间效率
结点:数据元素的存储映像。由数据域和指针域两部分组成;
链表:n 个结点由指针链组成一个链表。它是线性表的链式存储映像,称为线性表的链式存储结构。
单链表、双链表、多链表、循环链表:
结点只有一个指针域的链表,称为单链表或线性链表。
有两个指针域的链表,称为双链表(但未必是双向链表)。
有多个指针域的链表,称为多链表。
首尾相接的链表称为循环链表。
头指针是指向链表中第一个结点(或为头结点、或为首元结点)的指针;一般用头指针唯一标识一个单链表。
头结点是在链表的首元结点之前附设的一个结点;数据域内只放空表标志和表长等信息,它不计入表长度。
首元结点是指链表中存储线性表第一个数据元素a1的结点
设置头节点的好处:可以对空表、非空表的情况以及对首元结点进行统一处理,编程更方便。
表示空表:
无头结点时,当头指针的值为空时表示空表;
有头结点时,当头结点的指针域为空时表示空表。
typedef struct Node / * 结点类型定义 * /
{ elemtype data;
struct node *next;
} *LinkList,Node /* LinkList为单链表的类型名*/
结点的申请 p=(Node *)malloc(sizeof(Node));
结点的释放 free(p);
#include
#include
typedef int elemtype;
//定义链表
typedef struct Node
{elemtype data;
struct Node *next;
}*LinkList,Node;
//初始化单链表
LinkList InitList(LinkList L)
{
L=(LinkList)malloc(sizeof(Node));
L->next=NULL;
return L;
}
步骤:
①建立头结点L,并置其指针域为next为空。
②生成新结点p,如果生成新结点失败,则返回头结点L否则继续③。
③读入数据给新结点p的数据域。
④将新结点p的指针域指向首结点。
⑤修改头结点L的指针域,使它指向新结点p。
⑥重复步骤②~ ⑤,直到输入结束标志为止,返回头结点L。
//头插入链表
LinkList Create_LinkListF()
{elemtype ix;
LinkList L;
Node *p;
L=(LinkList)malloc(sizeof(Node));
L->next=NULL;
printf("\n请输入数据直到输入0结束:\n");
scanf(" %d",&ix);
while(ix!=0)
{p=(Node *)malloc(sizeof(Node));
p->data=ix;
p->next=L->next;
L->next=p;
scanf(" %d",&ix);
}
return (L);
}
步骤:
①建立头结点L,并置其指针域为next为空,同时尾指针rail也指向头结点。
②生成新结点p,如果生成新结点失败,则返回头结点L否则继续③。
③读入数据给新结点p的数据域,并将其指针域设为空。
④将新结点p连入尾结点的后面。
⑤修改尾指针,使它指向新结点p。
⑥重复步骤②~ ⑤,直到输入结束标志为止,返回头结点L。
//尾插法
LinkList Create_LinkListR()
{elemtype ix;
LinkList L;
Node *p,*tail;
L=(LinkList)malloc(sizeof(Node));
L->next=NULL;
tail=L;
printf("\n请输入数据直到输入0结束:\n");
scanf(" %d",&ix);
while(ix!=0)
{p=(Node *)malloc(sizeof(Node));
p->data=ix;
tail->next=p;
tail=p;
tail->next=NULL;
scanf(" %d",&ix);
}
return (L);
}
//遍历
void Print_LinkList(LinkList L)
{Node *p=L->next;
printf("输出链表:");
while(p!=NULL)
{printf("\t%d",p->data);
p=p->next;
}
}
//表长
int LinkList_Length(LinkList L)
{Node *p=L;
int j=0;
while(p->next)
{p=p->next;
j++;
}
return j;
}
//按序号查找
Node *GetData_LinkList(LinkList L,int i)
{Node *p;
int j=0;
if(i<=0)
return NULL;
p=L;
while(p->next&&jnext;
j++;
}
if(i==j) return p;
else return NULL;
}
//按内容查找
Node *Search_LinkList(LinkList L,elemtype key)
{Node *p;
p=L->next;
while(p)
if(p->data!=key)
p=p->next;
else
break;
return p;
}
//后插运算
void InsertAfter_LinkList(Node *p,elemtype x)
{Node *s;
s=(Node *)malloc(sizeof(Node));
s->data=x;
s->next=p->next;
p->next=s;
}
Node * findnode(LinkList L,elemtype x)
{Node *p=L;
while((p->next)&&(p->next->datanext;
return p;
}
//带头节点的后插运算//插入后链表任然升序
void data_INSERT(LinkList L,elemtype x)
{Node *s,*p;
s=(Node*)malloc(sizeof(Node));
s->data=x;
p=findnode(L,x);
s->next=p->next;
p->next=s;
}
//前插操作
void InserBefore_LinkList(LinkList L,Node *p,elemtype x)
{Node *s ,*q;
s=(Node *)malloc(sizeof(Node));
s->data=x;
q=L;
while(q->next!=p)
q=q->next;
s->next=p;
q->next=s;
}
//优化前插运算
void INSERTBEFORE1(Node *p,elemtype x)
{Node *s;
s=(Node *)malloc(sizeof(Node));
s->data=p->data;
s->next=p->next;
p->data=x;
p->next=s;
}
//在指定序号前插入
int InsList(LinkList L,int i,elemtype e)
{Node *pre,*s;
int k;
if(i<=0) return 0;
pre=L;
k=0;
while(pre!=NULL&&knext;
k=k+1;
}
if(!pre)
{printf("插入位置不合法!");
return 0;
}
s=(Node *)malloc(sizeof(Node));
s->data=e;
s->next=pre->next;
pre->next=s;
return 1;
}
//删除后继节点
int DeleteAfter_LinkList(Node *p)
{Node *r;
if(!p){return 0;}
r=p->next;
if(!r)
{return 0;}
p->next=r->next;
free(r);
return (1);
}
//删除指定位置节点
int DeleteNo_LinkList(LinkList L,int i,elemtype *e)
{Node *p,*r;
int k;
p=L;
k=0;
while(p->next!=NULL&&knext;
k=k+1;
}
if(k!=i-1)
{printf("删除节点的位置不合理!");
return 0;
}
r=p->next;
p->next=p->next->next;
*e=r->data;
free(r);
return 1;
}
//删除指定节点本身
int DeleteNode_LinkList(LinkList L,Node *p)
{Node *r;
if(p->next!=NULL)
{p->data=p->next->data;
return (DeleteAfter_LinkList(p));
}
else
{r=L;
while(r->next!=p)
r=r->next;
return (DeleteAfter_LinkList(r));
}
}
//置空表
LinkList SetNull_LinkList(LinkList L)
{while(L->next)
DeleteAfter_LinkList(L);
return (L);
}
编写实现单链表基本操作的以下函数,并在此基础上设计一个主程序完成如下功能:
⑴初始化单链表L;
⑵用头插法建立单链表L;
⑶用尾插法建立单链表L;
⑷输出单链表L的长度;
⑸输出单链表L的第i个元素(按位置查找);
⑹输出给定元素的位置(按内容查找);
⑺在第i个元素前插入给定元素(在第i个位置插入);
⑻删除单链表L的第i个元素;
⑼输出单链表;
⑽清空单链表(只保留头结点);
⑾菜单函数;
⑿单链表逆置;
main
↓
void menu()菜单
↓
LinkList InitList(LinkList L)初始化单链表
LinkList Create_LinkListF(LinkList L)头插入链表
LinkList Create_LinkListR(LinkList L)尾插法
void Print_LinkList(LinkList L)遍历
int LinkList_Length(LinkList L)表长
Node *GetData_LinkList(LinkList L)按序号查找
int Search_LinkList(LinkList L)按值查找
int InsList(LinkList L)在指定序号前插入
int DeleteNo_LinkList(LinkList L)删除指定位置节点
int DeleteAfter_LinkList(Node *p)删除后继节点
LinkList SetNull_LinkList(LinkList L)置空表
LinkList ReversePosition(LinkList L) 逆置单链表
1.菜单
2.创建链表
3.按头插入录入链表
4.输出链表长度
5.按序号查找
正确输入:
错误输入:
6.按内容查找:
正确输入:
错误输入:
7.在指定序号前插入
正确输入:
错误输入:
8.删除指定位置节点
9.输出链表
10逆置链表
11.清空链表
12.返回菜单
13.结束程序
14.尾插法建表
#include
#include
#include
#include
typedef int elemtype;
//定义链表
typedef struct Node
{elemtype data;
struct Node *next;
}*LinkList,Node;
//初始化单链表
LinkList InitList(LinkList L)
{
L=(LinkList)malloc(sizeof(Node));
L->next=NULL;
printf("创建成功。\n");
return L;
}
//头插入链表
LinkList Create_LinkListF(LinkList L)
{elemtype ix;
Node *p;
printf("请输入数据直到输入0结束:\n");
scanf(" %d",&ix);
while(ix!=0)
{p=(Node *)malloc(sizeof(Node));
p->data=ix;
p->next=L->next;
L->next=p;
scanf(" %d",&ix);
}
printf("初始化成功。\n");
return (L);
}
//尾插法
LinkList Create_LinkListR(LinkList L)
{elemtype ix;
Node *p,*tail;
tail=L;
printf("请输入数据直到输入0结束:\n");
scanf(" %d",&ix);
while(ix!=0)
{p=(Node *)malloc(sizeof(Node));
p->data=ix;
tail->next=p;
tail=p;
tail->next=NULL;
scanf(" %d",&ix);
}
printf("初始化成功。");
return (L);
}
//遍历
void Print_LinkList(LinkList L)
{
Node *p=L->next;
printf("\n输出链表:");
while(p!=NULL)
{printf("\t%d",p->data);
p=p->next;
}
printf("\n");
}
//表长
int LinkList_Length(LinkList L)
{Node *p=L;
int j=0;
while(p->next)
{p=p->next;
j++;
}
printf("链表表长为:%d\n",j);
return j;
}
//按序号查找
Node *GetData_LinkList(LinkList L)
{
Node *p;
int j=0,i;
printf("请输入需要查找的序号:");
scanf(" %d",&i) ;
if(i<=0)
{printf("输入不合法!\n");
return NULL;
}
p=L;
while(p->next&&jnext;
j++;
}
if(i==j) {printf("内容为%d\n",p->data);
return p;}
else {printf("输入不合法!\n");
return NULL;
}
}
//按值查找
int Search_LinkList(LinkList L)
{Node *p;
int i;
elemtype key;
printf("请输入需要查找的内容:");
scanf("%d",&key);
p=L->next;
while(p)
if(p->data!=key)
{p=p->next;
i++;}
else
{printf("序号为:%d\n",i+1);
break;
}
printf("未找到。\n");
return i;
}
//在指定序号前插入
int InsList(LinkList L)
{Node *pre,*s;
int k,i;
elemtype e;
printf("请输入插入位置和内容:");
scanf("%d %d",&i,&e);
if(i<=0) return 0;
pre=L;
k=0;
while(pre!=NULL&&knext;
k=k+1;
}
if(!pre)
{printf("\n插入位置不合法!\n");
return 0;
}
s=(Node *)malloc(sizeof(Node));
s->data=e;
s->next=pre->next;
pre->next=s;
printf("\n插入成功\n");
return 1;
}
//删除指定位置节点
int DeleteNo_LinkList(LinkList L)
{Node *p,*r;
int k,i;
printf("\n请输入删除位置:");
scanf("%d",&i);
p=L;
k=0;
while(p->next!=NULL&&knext;
k=k+1;
}
if(k!=i-1)
{printf("\n删除节点的位置不合理!\n");
return 0;
}
r=p->next;
p->next=p->next->next;
free(r);
printf("\n删除成功\n");
return 1;
}
//删除后继节点
int DeleteAfter_LinkList(Node *p)
{Node *r;
if(!p){return 0;}
r=p->next;
if(!r)
{return 0;}
p->next=r->next;
free(r);
return (1);
}
//置空表
LinkList SetNull_LinkList(LinkList L)
{while(L->next)
DeleteAfter_LinkList(L);
printf("清除成功!\n");
return (L);
}
Node *GetData2_LinkList(LinkList L,int i)
{
Node *p;
int j=0;
if(i<=0)
return NULL;
p=L;
while(p->next&&jnext;
j++;
}
if(i==j) return p;
else return NULL;
}
//逆置单链表
LinkList ReversePosition(LinkList L)
{LinkList L1;
Node *p,*q;
int i,j;
L1=(LinkList)malloc(sizeof(Node));
L1->next=NULL;
j=LinkList_Length(L);
q=L1;
for(i=1;i<=j;i++)
{
p=GetData2_LinkList(L,i);
q=(Node *)malloc(sizeof(Node));
q->data=p->data;
q->next=L1->next;
L1->next=q;
}
Print_LinkList(L1);
return (L1);
}
//菜单
void menu()
{
printf("--------1.初始化链表-----------------\n");
printf("--------2.头插入法建立顺序表---------\n");
printf("--------3.尾插入法建立顺序表---------\n");
printf("--------4.输出链表的长度-------------\n");
printf("--------5.按位置查找链表-------------\n");
printf("--------6.按内容查找链表-------------\n");
printf("--------7.插入元素-------------------\n");
printf("--------8.删除元素-------------------\n");
printf("--------9.输出链表-------------------\n");
printf("--------10.清空链表------------------\n");
printf("--------11.返回菜单------------------\n");
printf("--------12.逆置单链表----------------\n");
printf("--------13.退出程序------------------\n");
printf("-------------请输入需要执行的内容:\n");
}
//主函数
int main()
{LinkList L;
Node *q;
int i,a,quit=0;
menu();
while(1)
{
scanf("%d",&a);
switch(a)
{
case 1:L=InitList(L);break;
case 2:L=Create_LinkListF(L);break;
case 3:L=Create_LinkListR(L);break;
case 4:i=LinkList_Length(L);break;
case 5:q=GetData_LinkList(L);break;
case 6:i=Search_LinkList(L);break;
case 7:i=InsList(L);break;
case 8:i=DeleteNo_LinkList(L);break;
case 9:Print_LinkList(L);break;
case 10:L=SetNull_LinkList(L);break;
case 11:menu();break;
case 12:L=ReversePosition(L) ;break;
case 13:quit=1;break;
default:printf("输入1~13之间的数字\n");break;
}
if(quit==1)
{break;
}
}
return 0;
}