#include <stdio.h>
#include <stdlib.h>
// 线性链表
typedef int ElemType; // 任意数据类型
typedef int Status; // 函数返回数据类型
// 单链表
typedef struct LNode {
ElemType data; // 当前结点数据原色
struct LNode *next; // 后一个结点指针
}LNode, *LinkList;
// 获得对应位置的元素
Status GetELem(LinkList L, int i, ElemType *e){
// 获得第一个元素指针
LNode *p = L->next;
// 记录当前位置
int j = 1;
// 循环找到对应位置的地址
while(p && j<i){
p = p->next;
++j;
}
// 判断跳出while循环的原因,是否是查找到了需要的元素,即p指向的元素是否为空 或者 j是否大于i
if(!p || j>i) return 0;
// 存储需要的数据元素
*e=p->data;
return 1;
}
// 在指定位置插入指定元素
Status InsertElem(LinkList L, int i, ElemType e){
// 获得第一个数据元素的结点位置
LNode *p = L->next;
int j=1;
// 循环至i位置元素的前一个元素,因为只有找到前一个位置的元素,才能将第i个元素替换掉
for(; p&&j<i-1; j++)
p = p->next;
if(!p||j>i-1) return 0;
// 申请新的结点内存
LNode *newN = (LNode *)malloc(sizeof(LNode));
newN->data = e;
newN->next = p->next;
// 将i位置的地址替换成新地址
p->next = newN;
return 1;
}
// 删除对应位置的数据元素
Status DelElem(LinkList L,int i, ElemType *e){
// 前面和插入差不多
LNode *p = L->next;
int j=1;
for(; p&&j<i-1; j++)
p = p->next;
// 删除要看后面的后面是否超过长度,所以看后面一个是否为空
if(!(p->next)||j>i-1) return 0;
// 存储一下删除的位置,为了之后的释放结点
LNode *q = p->next;
*e = q->data;
p->next = p->next->next;
// 释放结点
free(q);
}
// 将两个有序列表合并为一个有序列表
void Merge(LinkList a, LinkList b, LinkList c){
LNode *pa, *pb, *pc;
pa = a->next; pb = b->next; pc = c = a;
while (pa && pb){
if(pa->data <= pb->data){
// pc->next=pa, 将pa接到pc后面; pc=pa相当于pc=pc->next; 然后将pa后移
pc->next = pa; pc = pa; pa = pa->next;
}else{
pc->next = pb; pc = pb; pb = pb->next;
}
}
// 将未为空的链表链接到最后
pc->next = pa?pa:pb;
// 释放b头结点空间
free(b);
}
// 初始化链表
LinkList InitList(){
LinkList l = (LinkList)malloc(sizeof(LNode)); // 用malloc给链表分配空间
l->next = NULL; // 初始化时,把next指向空
return l;
}
//创建链表---头插法
void CreateListHead(LinkList L, int n){
for(int i=n;i>0;--i){
// 申请一个结点的地址空间
LNode *p = (LNode*)malloc(sizeof(LNode));
// 存储输入的数据元素
scanf("%d",&p->data);
// 新结点的后一个节点指针存储为L的第一个数据元素位置指针
p->next = L->next;
// 将L的第一个数据元素位置指针指向p
L->next = p;
}
}
//创建链表---尾插法
void CreateListEnd(LinkList L, int n){
LNode *end;
// end指针指向L的头结点
end = L;
for(int i=0; i<n; i++){
// 若end当前指向的不是L结尾,循环指向结尾
while (end->next != NULL)
end = end->next;
// 申请一个结点的地址空间
LNode *p = (LinkList)malloc(sizeof(LinkList));
scanf("%d", &p->data);
p->next = NULL;
// 将结尾指针指向新的结点地址
end->next = p;
}
}
//输出单链表
void Display(LinkList L){
// 获得第一个结点地址
LNode *p = L->next;
printf("单链表的内容为:");
// 循环输出数据元素值
while(p){
printf("%d",p->data);
if(p->next) printf("->");
else printf("\n");
p = p->next;
}
}
int main()
{
LinkList l;
l = InitList();
printf("请输入链表长度:");
int n,k;
scanf("%d",&n);
printf("请选择插入方式(1 头插法 2 尾插法):");
scanf("%d",&k);
printf("请输入数据:\n");
if(k == 1)
CreateListHead(l, n);
else
CreateListEnd(l, n);
Display(l);
ElemType e;
GetELem(l,1,&e);
printf("%d\n",e);
printf("请输入插入元素和插入位置(以空格分隔):");
scanf("%d %d",&e,&k);
if(InsertElem(l,k,e) == 0)
printf("输入不合法!\n");
else
Display(l);
printf("请输入删除位置:");
scanf("%d",&k);
if(DelElem(l,k,&e) == 0)
printf("输入不合法!\n");
else{
printf("删除的元素为:%d\n",e);
Display(l);
}
return 0;
}
单链表c语言实现
最新推荐文章于 2024-07-14 12:00:00 发布