#include <stdio.h>
#include <string.h>
#include <malloc.h>
typedef int ElemType;
typedef int Status;
//单链表
//链表节点
typedef struct Lnode{
ElemType data;//数据域,可以是struct,也可以是int等。
struct Lnode *next;//指针域
}Lnode,*LinkList;
//创建空链表
Status creatList(LinkList &L){
L = (LinkList)malloc(sizeof(Lnode));//申请一个节点空间,为头结点
L->next = NULL;//给头结点next域给空值;
return 1;
}
//头插法创建单链表,倒叙排列,后入的元素放在头位置上
void creatHeadList(LinkList &L,int n){//n为节点个数
L = (LinkList)malloc(sizeof(Lnode));
L->next = NULL;//先创建一个带头结点的单链表
for(int i = n;i>0;i--){
Lnode *p = (LinkList)malloc(sizeof(Lnode));
scanf("%d",&p->data);
p->next = L->next;//插入到表头
L->next = p;//更改头节点位置,指向最新元素
}
}
//尾插法创建单链表,从后面一个个接入
void creatTailList(LinkList &L,int n){//n为节点个数
L = (LinkList)malloc(sizeof(Lnode));
L->next = NULL;//先创建一个带头结点的单链表
Lnode *last = L;//尾结点last
for(int i = 1;i<=n;i++){
Lnode *p = (LinkList)malloc(sizeof(Lnode));//建立新节点接收数据
scanf("%d",&p->data);
p->next = NULL;//一定要给节点next值赋值为NULL
last->next = p;//新节点p插入到表尾
last = p;//尾结点last更新位置,指向新的尾结点
}
}
//判断链表是否为空
int isEmpty(LinkList L){//若L为空,返回1,不空返回0
if(L->next)//非空
return 0;
else
return 1;
}
//销毁单链表L
int destroyList(LinkList &L){
Lnode *p;
while(L){
p = L;
L = L->next;//头结点指向下一个,一个一个销毁
free(p);
}
return 1;
}
//清空单链表,头尾结点还在,只是清空内容
int clearList(LinkList &L){
Lnode *p,*q;//p指向第一个元素,q连续指向后面元素,用来逐个清空
p = L->next;
while(p){
q = p->next;
free(p);
p = q;
}
L->next = NULL;//头结点指针域为空
return 1;
}
//求单链表L的表长
int listLength(LinkList L){
Lnode *p;
p = L->next;//p指向第一个结点
int count = 0;//计数器
while(p){//遍历单链表,统计结点数
count++;
p = p->next;
}
return count;
}
//获取第i个元素值,用e返回,e传过来的是地址
int getElem(LinkList L,int i,ElemType &e){
Lnode *p = L->next;
int j = 1;//初始化
while(p && j<i){//向后扫描,直到p指向第i个元素或者p为空
p = p->next;
j++;
}
if(!p || j>i){//第i个元素不存在
return 0;
}
e = p->data;//取第一个元素
return 1;
}//getElem
//查找链表中指定元素值的位置,若有则返回该地址,没有返回NULL
Lnode *locateElem(LinkList L,ElemType e){
Lnode *p = L->next;
while(p && p->data !=e){
p = p->next;
}
return p;//找到了则直接返回p的地址,找不到也会直接返回NULL,所以直接return p 就可以。
}
//查找链表中指定元素值的位置,若有则返回位置序号,没有返回0
int locateElem(LinkList &L,ElemType e){
Lnode *p = L->next;
int j = 1;//用来标记下标位置
while(p && p->data !=e){
p = p->next;
j++;
}
if(p)//p不为空,说明跳出循环的条件是找到了相同元素值
return j;
else//查找失败
return 0;
}
//在单链表中第i个元素之前插入数据元素e
int insertList(LinkList &L,int i,ElemType e){
Lnode *p = L;
int j = 0;
while(p && j<i-1){
p = p->next;
j++;
}
//此时p指向的是第i-1个节点的地址
if(!p || j>i-1)//i大于表长+1 或者小于1,插入位置非法
return 0;
Lnode *q = (LinkList)malloc(sizeof(Lnode));//生成新节点
q->data = e;
q->next = p->next;//将节点q插入到L中
p->next = q;
return 1;
}
//在指定节点p前插入元素(先在p后面插入节点,然后换元,妙啊)
int insertPriorNode(Lnode *p,ElemType e){
if(p == NULL){//p为空
return 0;
}
Lnode *s = (Lnode *)malloc(sizeof(Lnode));
if(s == NULL)//分配失败
return 0;
s->next = p->next;
p->next = s;//s接到p后面
s->data = p->data;//p中元素赋给s
p->data = e;//p中元素用e覆盖,实现完整插入工作
return 1;
}
//删除第i个节点,被删数据值用e暂存
int deleteList(LinkList &L,int i,ElemType &e){
if(i < 1)//i值不合法
return 0;
Lnode *p = L;
int j = 0;
while(p && j<i-1){
p = p->next;
j++;
}
if(!(p->next))//如果i处节点为NULL或者i超出链表长度,返回错误
return 0;
Lnode *q = p->next;//q节点指向i处
p->next = q->next;//将i前节点指向i后节点,跳过i处
e = q->data;//e暂存被删元素值
free(q);//释放i处节点
return 1;
}
//删除指定节点p(偷天换日)
int deleteNode(Lnode *p){//此代码限制条件,p也不能为最后尾结点,必须为尾结点前面的节点。】】】】
if(p == NULL)//p为空
return 0;
Lnode *q = p->next; //令q指向*p的后继节点
p->data = q->data;//p和后继节点交换数据域
p->next = q->next;//将*q节点从链中断开
free(q);
return 1;
}
//遍历输出链表
void printList(LinkList L){
Lnode *p = L->next;
if(!p)
return;
printf("%d",p->data);
p = p->next;
while(p){
printf(" %d",p->data);
p = p->next;
}
}
int main()
{
LinkList L;
creatTailList(L,5);
printList(L);
printf("\n");
Lnode *p = L->next->next->next;
deleteNode(p);
printList(L);
// int x;
// deleteList(L,3,x);
// printList(L);
return 0;
}