1、单链表的基本概念
在链式结构中,除了要存储数据元素的信息外,还要存储它的后继元素的存储地址。因此,为了表示每个数据元素ai与其直接后继元素ai+1之间的逻辑关系,对数据ai来说,除了存储其本身的信息之外,还需要存储一个指示其直接后继的信息(即直接后继的存储位置)。我们吧把存储数据元素信息的域称为数据域,把存储直接后继位置的域称为指针域。指针域中存储的信息称做指针或链。这两部分信息组成数据元素ai的存储映像,称为结点(Node)。
n个结点(ai的存储映像)链结成一个链表,即为线性表(a1, a2, …, an)的链式存储结构,因为此链表的每个结点中只包含一个指针域,所以叫做单链表。
把链表中第一个结点的存储位置叫做头指针。
有时为了方便对链表进行操作,会在单链表的第一个结点前附设一个节点,称为头结点,此时头指针指向的结点就是头结点。
空链表,头结点的直接后继为空。
假设p是指向线性表第i个数据元素的指针,p->data表示第i个位置的数据域,p->next表示第i+1个位置的指针域,则第p+i个数据元素可表示为:
#include<stdio.h>
#include<stdlib.h>
#define maxlen 100 //数据最大长度 maxlen
#define ok 1 //操作成功标识 ok
#define no -1 //操作失败标识 no
typedef int Elemtype; //Elemtype是数据的类型
typedef int cz; //cz为执行操作时函数的类型
typedef struct Node{ //构造结点Node
Elemtype data; //存储数据
struct Node *next; //指向下一个结点
}Node;
typedef struct{ //构造单链表的结构LinkNode
int len; //len是表的长度
Node *next;
}*Linklist;
cz Initlist(Linklist *L) //初始化单链表表(有头结点)
{
Linklist p=(Linklist)malloc(sizeof(Linklist)*maxlen); //头指针
Node *q=(Node *)malloc(sizeof(Node)); //头结点
q->next=NULL; //头结点后继指向NULL
p->next=q; //头指针指向头结点
p->len=0;
(*L)=p;
return ok;
}
cz Listinsert(Linklist *L,int n,Elemtype e) //插入 在第n位插入e元素
{
if(n>(*L)->len+1||n<1){ //判断i是否符合条件
return no;
}
Node *p=(*L)->next; //指向头结点
for(int i=1;i<n;i++) //找到第i位的前结点
{
p=p->next; //p指向第i位的前结点
}
Node *q=(Node *)malloc(sizeof(Node)); //生成一个新的结点
q->data=e;
q->next=p->next; //先把q的后继结点连接到p->next
p->next=q; //再把q连接到p的后继结点上
(*L)->len++; //长度加1
return ok;
}
cz Listdel(Linklist *L, int n) //删除第n位元素
{
if((*L)->len==0||n<1||n>(*L)->len){ //判断n是否符合条件且L长度不为1
return no;
}
Node *p=(*L)->next; //指向头结点
Node *q; //用来指向第n位结点
for(int i=1;i<n;i++) //找到第n位的前结点
{
p=p->next; //p指向第n位的前结点即n-1位
}
q=p->next;
p->next=q->next; //第n-1位指向第n+1位
free(q); //释放空间
(*L)->len--; //长度减1
return ok;
}
cz Getelem(Linklist L, int n, Elemtype *e) //获取第n位元素的值并把其传给e
{
if(n<1||n>L->len){ //判断n是否符合条件且L长度不为1
return no;
}
Node *p=L->next; //指向头结点
for(int i=1;i<n+1;i++) //找到第n位结点
{
p=p->next; //p指向第n位结点
}
(*e)=p->data;//给值
return ok;
}
void Output(Linklist L) //遍历输出
{
printf("当前链表表的长度:%d\n", L->len);
Node *p=L->next->next;
for(int i=0;i< L->len;i++){ //遍历整个L
printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
int main()
{
Linklist *L; //创建一个单链表表
Initlist(L); //初始化
int i=1;
int n;
Elemtype e;
printf("请输入数据:(当输入的值为-1时输入结束)\n");
while(1){
scanf("%d",&n);
if(n== -1) break;
e=(Elemtype)n;
Listinsert(L,i,e);
i++;
}
printf("------------------------以上数据已插入表中-------------------------\n");
printf("\n");
printf("---------------------------遍历表中的数据---------------------------\n");
Output(*L);
printf("---------------------------删除表中的数据---------------------------\n");
printf("请输入欲删除数据的位置:");
scanf("%d",&n);
Listdel(L,n);
Output(*L);
printf("---------------------------获取表中的数据---------------------------\n");
Elemtype x;
printf("请输入欲获取数据的位置:");
scanf("%d",&n);
Getelem(*L,n,&x);
printf("第%d位元素的值为:%d\n",n,x);
return 0;
}