09月22日, 2014 362次
关于 !p 如何理解.符号 ! 用于把真变假, 假变真例如,!5的值是0(false,假), !0的值是1(true,真)假设链表L有5个数据,分别是 10,20,30,40,50位置范围是从第1位到第5位.假设要找第6个元素(结点),可以看到,i=6已经超出范围.执行语句while(p && j<i)之后,此时,i,j,p的数值分别是:i=6, j=6, p=00000000, !p=1p等于空指针(NULL),也就是p等于0, 而!p等于1(这是true,真)由于 !p是真, j>i是假, 满足 if(!p || j>i) 的条件,所以,执行return ERROR, 函数GetElem()返回ERRORif(!p || j>i) // 第i个元素不存在{ return ERROR;}e=p->data; // 取第i个元素return OK;假设要找第0个元素(结点),可以看到,i=0超出范围.执行语句while(p && j<i)之后,此时,i,j,p的数值分别是:i=0, j=1, p=00942A70, !p=0, e=10p等于第1个结点的指针,p不等于0, 而!p等于0(这是false,假)由于 !p是假,j>i是真, 满足 if(!p || j>i) 的条件,所以,执行return ERROR, 函数GetElem()返回ERROR假设要找第3个元素(结点),i=3在范围之内.执行语句while(p && j<i)之后,此时,i,j,p的数值分别是:i=3, j=3, p=00942A90, !p=0, e=30p等于第3个结点的指针,p不等于0, 而!p等于0(这是false,假)由于 !p是假,j>i是假, 不满足 if(!p || j>i) 的条件,所以,继续往下执行e=p->data以及return OK, 函数GetElem()返回OK测试结果:链表里的数据有: 10 20 30 40 50测试: i=6, j=6, p=00000000, !p=1第6位超出链表的范围.测试: i=0, j=1, p=00942A70, !p=0, e=10第0位超出链表的范围.测试: i=3, j=3, p=00942A90, !p=0, e=30第3个结点是 30//用C++编译器进行测试#include<stdio.h>#include<stdlib.h>#define OVERFLOW -1#define ERROR 0#define OK 1typedef int ElemType;typedef int Status;typedef struct LNode{ ElemType data; struct LNode *next;}LNode, *LinkList;//创建链表void CreateList(LinkList &L,int n){ LinkList newNode; //新结点 LinkList ptr; //当前结点 int i; //这是带头结点的单链表 L=(LinkList)malloc(sizeof(LNode)); L->next=NULL; ptr=L; for(i=0;i<n;i++) { newNode=(LinkList)malloc(sizeof(LNode)); newNode->data=(i+1)*10; newNode->next=NULL; ptr->next=newNode; ptr=newNode; }}//打印链表void DispList(LinkList L){ LinkList ptr; //当前结点 ptr=L->next; if(ptr==NULL) { printf("链表没有数据.\n"); return; } while(ptr != NULL) { printf("%d ",ptr->data); ptr=ptr->next; } printf("\n");}//查找第i个结点Status GetElem(LinkList L,int i,ElemType &e) // 算法2.8{ // L为带头结点的单链表的头指针。当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR int j=1; // j为计数器 LinkList p=L->next; // p指向第一个结点 while(p && j<i) // 顺指针向后查找,直到p指向第i个元素或p为空 { p=p->next; j++; } ////////测试 if(p==NULL) { printf("\n测试: i=%d, j=%d, p=%p, !p=%x\n",i,j,p,!p); } else { printf("\n测试: i=%d, j=%d, p=%p, !p=%x, e=%d\n",i,j,p,!p,p->data); } //////// if(!p || j>i) // 第i个元素不存在 { return ERROR; } e=p->data; // 取第i个元素 return OK;}int main(){ LinkList L; int i; ElemType e; Status ret; CreateList(L,5); printf("链表里的数据有: "); DispList(L); i = 6; ret=GetElem(L,i,e); if(ret==ERROR) { printf("第%d位超出链表的范围.\n",i); } else { printf("第 %d 个结点是 %d\n",i,e); } i = 0; ret=GetElem(L,i,e); if(ret==ERROR) { printf("第%d位超出链表的范围.\n",i); } else { printf("第%d个结点是 %d\n",i,e); } i = 3; ret=GetElem(L,i,e); if(ret==ERROR) { printf("第%d位超出链表的范围.\n",i); } else { printf("第%d个结点是 %d\n",i,e); } return 0;}
这种情况就是为了保证考虑周全,当i取0的时候不就是符合条件了嘛,个人理解就是严谨性吧 本回答被提问者采纳
数据结构有很多 最好贴出全文 不然得不到好答案…… 更多追问追答 追问 这个算法能不能删除最后一个元素,也就是说,L共有n个元素,删除第n个元素。执行完while语句,j=n-1,p也到了第n-1个结点,再执行if,p->next为空,if成立,返回ERROR.对不? 先谢啦! 本回答由提问者推荐
没错,!p指p是空指针
当你传参数i>n时,while语句处跳出条件是p为空了,此时的 j 必然小于 i ,那么if语句中的(!p)就为真了,则返回error。 本回答由提问者推荐
!p->next什么意思 相当于p->next==NULL
线性表有顺序存储和链式存储,数据结构的代码都比较多,不是几行就可以了,下面是链表(线性表的链式存储结构)的基本操作,你看看#include "stdio.h"#include "stdlib.h"#include"string.h"#define OK 1#define ERROR 0typedef char ElemType[10];//数据元素类型typedef struct LNode{ //单链表结构 ElemType data; struct LNode *next;}LNode,*LinkList;void CreateList_L(LinkList &L,int n){//顺序创建有n个结点的单链表 LinkList p,q; int i; L=(LinkList)malloc(sizeof(LNode));//生成头节点 if(!L) return ; L->next=NULL;q=L; for(i=1;i<=n;++i) { p=(LinkList)malloc(sizeof(LNode));//生成新节点 printf("Input NO.%d :",i); scanf("%s",p->data); p->next=NULL;q->next=p; q=p; }}void Display_L(LinkList L){//L为头指针,显示单链表的每个元素 LinkList p=L->next; while(p) { printf("%s\t",p->data); p=p->next; } printf("\n");}int GetElem_L(LinkList L,int i,ElemType e){//L为单链表的头指针,取为位序为i的元素值,并赋值给变量e LinkList p=L->next; int j=1; while(p&&j<i) { p=p->next; j++; } if(!p||j>i) return ERROR; strcpy(e,p->data);return OK;}int ListInsert_L(LinkList &L,int i,ElemType e) {//L为单链表的头指针,表示在位序为i的元素前插入数据e LinkList p=L,s;int j=0; while(p&&j<i-1) //定位在第i-1节点上 { p=p->next; ++j; } if(!p||j>i-1) return ERROR;//i值不合理 s=(LinkList)malloc(sizeof(LNode)); strcpy(s->data,e); s->next=p->next; p->next=s; return OK;}int ListDelete_L(LinkList &L,int i,ElemType e){//L为单链表的头指针,删除位序为i的数据元素,并将其值赋值给e LinkList p=L,q; int j=0; while(p&&j<i-1) { p=p->next; ++j; } if(!p||j>i-1) return ERROR;//i值不合理 q=p->next;p->next =q->next ;//删除结点 strcpy(e,q->data );free(q);//释放结点 return OK;}void main(){ LinkList L; ElemType e; int n; printf("请输入单链表的长度n="); scanf("%d",&n); CreateList_L(L,n); printf("\n原始单链表是:");Display_L(L); if(GetElem_L(L,3,e))printf("\n3号结点的内容是:%s\n",e); if(ListDelete_L(L,6,e)) printf("\n删除6号结点后的单链表是:");Display_L(L); if(ListInsert_L(L,4,"李")) printf("\n在4号结点前插入后的单链表是:\n");Display_L(L);}