#include<stdio.h>
#define maxsize 10
//我们这次要做的是在静态分配的情况下进行顺序表的插入
//定义一个顺序表
typedef struct{
int data[maxsize];
int length;
}sqelist;
//初始化顺序表
void Initlist(sqelist &L){
L.length=0;//静态初始化就不需要申请内存空间了是吗
}
//做出插入的步骤,考虑代码的健壮性
//因为我们对于是否插入成功要给予反馈所以这边定义整个函数为布尔类型
bool Listinsert(sqelist &L,int i,int e){//在顺序表的第i个位置插入e
//有两种情况不能插入,1插入位置不在顺序表范围内,2顺序表已满
//所以在插入前对i进行检查,这个函数最后面返回true,我们在判断时就应该去排除错误的
if(i<1||i>L.length+1){//这里的L.length+1被允许应该是能在顺序表最后面,也就是再增加
//一个元素,综上,如果这两个条件有一个不满足也就是插入失败
return false;
}
//还有一个情况2
if(L.length>=maxsize){
return false;
}
for(int j=L.length;j>=i;j--){
//不能从插入的后一个位置一个个往后退,因为会被覆盖掉,应该从最后一个,倒数第二个
//依次往后退
L.data[j]=L.data[j-1];//后边元素往后退之后
L.data[i-1]=e;//进行插入步骤
L.length+=1;//插入完成后进行顺序表长度增加
}
printf("恭喜你插入成功");
return true;
}
int main(){
sqelist L;
Initlist(L);
Listinsert(L,3,3);
return 0;
}
//这个是按照位序插入
bool Insertlist(Linklist &L,int i,Elemtype e){
//布尔型是为了给予使用者反馈,是否插入成功,括号里边定义一个指向链
//表头节点的指针,在第i个节点,插入e
if(i<1)//节点计数只有从第一个第二个开始,也就是说你插入的位置不能小于1
return false;
//而我们插入一个节点需要找到所插入位置的前一个节点
LNode *p;//除了头指针之外我们还要定义一个指针去寻找要插入的位置
int j=0;//这里告诉我们当前指针p指向了第几个位置,用来跟插入的位置i进行比较
p=L;//让指针p也指向头节点,也就是上面L指针指向的位置
//因为不确定会移动多少次,所以用一个循环
while(p!=NULL&&j<i-1){
//指针p不能为NULL是为了防止i值不合法,比如链表一共四个,而i=6,那么
//在要指向第五个的时候就会报错,因为根本无法插入第六个
//而j<i-1是因为要找到i前面的那个,而且不能等于,倘若等于的话
//就会执行下一次循环了
p=p->next;//指针p一个一个往前走
j++;//也要跟上步伐++用以判断和i的距离
}
if(p==NULL)//如果在上面指针p移动的过程中出现i值不合法,我们这边要给予
//用户反馈,而上面仅仅判断没有给用户反馈
return false;
//等上面检验步骤都合理,即可执行插入操作
//第一步先给要插入元素向内存申请一个空间,使用malloc函数
LNode* s=(LNode*)malloc(sizeof(LNode));//计算出一个LNode类型的空间大小,申请
//因为malloc函数会返回一个指针,强转为这个类型的指针,在赋值给指针s
s->data=e;//先对插入的元素赋值
//第一步必须让插入元素的指针指向p的next所指向的元素,也就是s要指向自己
//插入位置的下一个元素
s->next=p->next;
//然后再让p指向s,也就是p指针指向的元素跟s指针的元素衔接起来
p->next=s;
//完成,return true
return true;
}
//接下来练习后插操作
//也用布尔类型去给予使用者反馈
bool houcha(LNode *p,Elemtype k){//在指针
//后边插入元素k
//第一步先来看看p指针本身不能为空
if(p==NULL)
return false;
//先来定义一个指针去指向自己要插入的那个元素
LNode *s=(LNode*)malloc(sizeof(Elemtype));
//好像是要检查自己这个指针的内存是否分配完毕
if(s==NULL){
printf("插入元素的内存分配失败");
return false;
}
//检查完之后就来进行后插吧
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
//实现节点的前插操作,可以说是偷梁换柱
//先后插一个元素,再定义出一个中间元素,接着把数据复制过去
bool qianca(LNode *p){
//在指针p前面插入元素e,我们先为要插入的元素
//定义一个内存空间
Elemtype e;
printf("请输入您要进行前插操作的数值");
scanf("%d",e);
s->data=e;
LNode *s=(LNode*)malloc(sizeof(Elemtype));
if(p==NULL||s==NULL)
{
printf("指针所指向元素不存在或者要插入元素内存分配失败");
return false;
}
//没有问题我们就可以开始分配
Elemtype haha=p->data;//我们先把指针P的数值复制给haha
//我也不知道是先把值分配好还是先把位置分配好应该问题不大吧
p->data=s->data;
s->data=haha;
//接下来处理位置
s->next=p->next;
p->next=s;
return true;
}
//下面我们进行按照位序删除,这里面我们还要返回被删除的数据
bool shanchu(LNode *p,int i,Elemtype &e){
//这里的p指针是要删除那个元素的前驱节点,并且节点P一般第一下是指向头节点的,e是因为要返回被删除元素的数据所以是引用类型
//先要找到被删除那个元素的前去节点
//int j;//是表示是指针p到第几个,这里错了一半被删除元素位置都是传进来的
int i;//这个应该是自己要删除的是第几个元素
if(i<1||p==NULL)//因为p指向的是被删除节点的前驱节点,所以一定不能是空
return false;
//因为指针p和整数j都要一个个找所以运用for循环,其实课程中用的是while循环
for(j=0;j>0;j<i-1){
p=p->next;
j++;
}
LNode *q=(LNode*)malloc(sizeof(Elemtype));
q=p->next;
//先让被删除元素(也就是q指针指向的那个节点)的前驱节点p指向q的下一个节点
//也就是跳过被删除节点,然后再释放节点q的空间、
e=q->data;//这步肯定要放在释放q节点之前不然被释放了怎么拿到数据
p->next=q->next;
free(q);
return e;
}
//接下来说说按照指定位置删除节点
bool deletejie(LNode *p){
//视频里说的是删除指针p所指向的那个节点,这里边的中心思想就是在要删除
//的这个节点后面添加一个指针q指向被删除元素的后一个节点,将q所指向的那个值
//赋给要被删除的那个节点,再把指针q所指向的删除即可
LNode *q=(LNode*)malloc(sizeof(Elemtype));
q=p->next;
if(q==NULL){//这里就是自己想的为了应付被删除节点是
//最后一个节点的情况,但是这个判断之前都是用于判断
//这个指针内存是否申请成功,视频说是需要从头一个个开始找,而且无伤大雅
free(p);
}
p->data=q->data;
p->next=q->next;
free(q);
return true;
}
//单链表的按位查找,因为我们后边需要返回的是一个节点,
//所以定义的时候就是说函数的类型是LNode*,这边都是由头节点的情况
LNode* Getelem(Linklist L,int i){
//前面也说过Linklist侧重的是链表,i是第几个位置
//首先先确定查找位置是否合法
if(i<0){
printf("输入的位置不合理");
return false;
}
//s申请一个指针先指向头节点,再逐步移动要删除的那个位置
LNode* p=(LNode*)malloc(sixeof(Elemtype));
p=L;
//定义一个变量j用力检测和传入位置i的距离
int j=0;
while(p!=NULL&&j<i){
//这里的检验条件就是,指针P不能指向空的,就像
//到了最后一个节点这个情况,j也就是到达i前面一个节点
p=p->next;
j++;
}
return p;//这里就会返回指针p所指向的内容
}
//接下来我们学习按值查找,同样的是返回一个节点
//如果传入比较的是结构体类型数据,之前讲过分别比较结构体里面的
//的元素,还有在网上查着用memcmp()这个方法,我也不太清楚
LNode* Locatelem(Linklist L,Elemtype i){
//要查找的值是由变量i 传输过来接下来去比较
//定义一个头指针先指向头节点,视频里指向的好像是头节点的下一个节点
LNode* p=(LNode*)malloc(sizeof(Elemtype));
//直接使用指针p的数据域与传入数值进行比较,一个个比较
//所以肯定是在循环中,要预防指针P不合法位置的情况
while(p!=NULL&&p->data!=i){
p=p->next;//也就是再指针p不合法值的情况下一个个节点
}//的数据域进行比较
return p;//一旦发现找到那个数值,也就是判断条件不满足
//我们直接返回指针P对应数值
}
//老师提了一下说,如何得到链式存储单链表的长度,只需要
//在指针依次遍历链表是定义一个变量依次累加,最后返回即可
//这里学习用尾插法建立单链表,之前学习过在特定位置插入也可以让
//那个是在最后位置插入,但是因为要从头节点依次遍历找到那个位置所以不妥
//我们这里运用尾插法建立单链表,先是有一个头节点,还要定义一个尾指针
//一直指向尾部便于统计链表长度,也要建立一个指针用于指向新添加的节点
Linklist weichafa(Linklist &L){
int i;//这个变量用来接受要插入的节点数据
printf("请输入您要插入的节点数据");
scanf("%d",&i);//这个是scanf函数,用来把输入的值赋给变量i
//先建立好头节点
LNode *l=(LNode*)malloc(sizeof(Elemtype));
l->next=NULL;//一般不都是这样建立头指针吗,
//视频中是:L=(Linklist)malloc(sizeof(LNode));说这个是建立头节点
//我们还需要两个指针,一个尾指针一个用来指向新插入的节点
LNode *r,*s=l;//这里是先让两个指针指向头节,还没有向内存申请相应的空间
//鉴于尾指针r和指针s需要在有限定条件下移动,使用while循环
while(i!==9999){//随意写的限定条件
s=(LNode*)malloc(sizeof(Elemtype));//这里是给指针s申请内存空间
s->data=i;
s=r->next;//先让s往后走
r=s;//r再跟上
//最上面的节点数据输入是为了现有一个数去验证数值的合理性
scanf("%d",&i);//接着接收新插入的节点数据
}
r->next=NULL;//当插入的节点数据不合理时,也就是终止插入了
return L;
}
//如果我们要使用头插法,也就是在头节点后面去插入节点
//不是很懂,先按照视频里边打一遍
Linklist List_HeadInsert(LinkList &L){
LNode *s;//先建立一个指针s
int x;//定义变量i
L=(LinkList)malloc(sizeof(LNode));//这里时设置一个头节点。
L->next=NULL;
scanf("%d",&x);
while(x!=9999){
s=(LNode *)malloc(sizeof(LNode));//前面已经定义了s是一个指针
s->data=x;
s->next=L->next;
L->next=s;
scanf("%d",&x);//继续接受插入的数值
}
return L;
}