#include<stdio.h>
#include<stdlib.h>
typedef struct Node{
int data;
struct Node* next;
}Node;
typedef Node* list;
bool initNode(list &L);
bool printNode(list L);
bool Empty(list L);
bool nextNodeInsert(Node *p,int data);
Node* getElem(list L,int i);
bool befNodeinsert(Node* p,int data);
bool insertNode(list L,int i,int data);
bool deleteNode(list L,int i,int &e);
Node* Locatelem(list L,int data);
int lengthlist(list L);
bool createlist_tail(list &L);
bool createlist_pri(list &L); //头插法通常可以用于逆序输出链表
int main(){
int e=0;
list L; //头指针 ,也可以认为创建一个链表 ,通过头指针来找到链表
// initNode(L);
// insertNode(L,1,55);
// insertNode(L,2,67);
// insertNode(L,1,23);
createlist_pri(L);
deleteNode(L,1,e);
printNode(L);
printf("删除的数值是%d\n",e);
// printf("值为67的节点%d\n",Locatelem(L,67)->data);
printf("链表长度为%d",lengthlist(L));
}
bool initNode(list &L){ //创建一个带头结点的单.当需要改变L的值并带出去这时候就需要引用
L= (Node *)malloc(sizeof(struct Node));
if(L==NULL) return false; //这个有问题!!!!!!
L->next=NULL;
return true;
}
bool Empty(list L){ //判空
return (L->next==NULL); //判断带头结点的链表是否为空。
}
bool printNode(list L){ //遍历操作
Node* p= L->next;
while(p!=NULL){
printf("%d\n",p->data);
p=p->next;
}
return true;
}
bool nextNodeInsert(Node *p,int data){ //后插操作
if(p==NULL) return false;
Node* s=(Node*)malloc(sizeof(Node));
if(s==NULL) return false;
s->data=data;
s->next=p->next;
p->next=s;
return true;
}
Node* getElem(list L,int i){ //找第i个位置的节点。i是所找位置的节点
int j=0; //标记现在在哪个节点;
Node* p; //用于寻找所需节点,通过p的后移来判断哪个节点是要找的
p=L;
if(i<0) return NULL;
while(p!=NULL&&j<i){ //如果输入的值过大,p就会等于null,此时循环就不再执行
p=p->next; //如果不是所需节点p就往后走
j++; //j也代表p的位置
}
return p;
}
bool befNodeinsert(Node* p,int data){ //节点前插操作
Node* s=(Node*)malloc(sizeof(Node));
if(s=NULL) return false;
s->next=p->next; //在p后创建了一个新节点
p->next=s;
s->data=p->data; //把p中的数据放到新的p后节点s中
p->data=data; //相当于将原来的节点后的内容移动到下一个位置,
return true; //将数据后移相当于在前面新创了一个节点
}
bool insertNode(list L,int i,int data){ //在第i个位置插入一个新节点 ,指定节点插入
Node* p;
p=getElem(L,i-1);
nextNodeInsert(p,data);
return true;
}
bool deleteNode(list L,int i,int &e){ //删除第i节点后的一个节点,并将值返回给e
if(i<0) return false;
Node* p=getElem(L,i-1);
Node* m=p->next;
p->next=m->next;
e=m->data;
free(m);
return true;
}
Node* Locatelem(list L,int data){ //按值查找,返回链表上数据域是data的节点地址
Node* p=L;
while(p!=NULL&&p->data!=data){
p=p->next;
}
return p;
}
int lengthlist(list L){
Node* p=L->next; //p指向第一个节点 ,从首节点开始数有几个不为空的节点
int j=0;
while(p){
p=p->next;
j++;
}
return j;
}
bool createlist_tail(list &L){ //尾插法创建带头结点的链表
L=(list)malloc(sizeof(Node));
L->next=NULL; //初始化链表
Node* s,*r; //用两个指针来指向链表尾部 ,
int data=0;
s=r=L;
while(data!=888){
Node* p=(Node*)malloc(sizeof(Node));
if(p==NULL) return false;
scanf("%d",&data);
if(data==888) break;
s=p; //s指向新申请的节点p
s->next=r->next; // 让新申请的节点的next,指向尾结点的next
s->data=data;
r->next=s; //原来的节点的next指向新的节点p(s和p指向的地址相同)
r=s; //r也指向最后一个节点
return true;
}
}
bool createlist_pri(list &L){ //头插法创建带表头的链表 !!头插法经常用在逆序输出链表
L=(list)malloc(sizeof(Node));
L->next=NULL; //链表的初始化
int data=0; //data用于给节点赋值
while(data!=888){
Node* p=(list)malloc(sizeof(Node)); //每次都插入在头结点之后
scanf("%d",&data);
if(data==888) break; //输入特定值后结束
p->next=L->next; //新节点的下一个节点指向头结点的下一个节点
L->next=p; //每次都插入到头结点后面
p->data=data;
}
return true;
}
链表的创建实际上就是初始化加上指定位置的后插操作