带头节点的单链表实现
#include#include //包含动态分配内存空间函数 malloc()和释放空间函数free() #include typedef struct LNode{ int data; struct LNode *next; }LNode,*LinkList; LNode* List_Tail(LNode *L){//尾插法建立单链表 L=(LNode*)malloc(sizeof(LNode)); //此处为了使尾插法得时间复杂度降到O(n)级别,除头节点外额外设置了一个尾指针r (for rear) LNode *s; LNode *r=L;//初始的表尾和表头重合 同时rear==L也是队的判空条件 不过这都是后话了 int x; scanf("%d",&x); while(x!=9527){ s=(LNode*)malloc(sizeof(LNode)); s->data=x; r->next=s; r=s; scanf("%d",&x); } r->next=NULL;//表尾元素后继置空 return L; } LNode* List_HeadInsert(LNode *L){//头插法建立单链表 LNode *s; L=(LNode*)malloc(sizeof(LNode)); L->next=NULL;//置空初始操作 因为内存中可能有脏数据影响单链表建立 L->data=5; int x; printf("请输入单链表元素"); scanf("%d",&x); while(x!=9527){ s=(LNode*)malloc(sizeof(LNode)); s->data=x; s->next=L->next; L->next=s; scanf("%d",&x); } return L; } int length(LinkList L){//度量单链表长度 LNode*p=L->next;//p从第一个数据节点开始 int len=0; if(L==NULL)return len; while(p!=NULL){ p=p->next; len++; } return len; } int Empty(LinkList L){//本应将返回值定义为_Bool类型的函数,暂将该函数返回值定为int if(L->next==NULL)return 1; else return 0; } void PrintList(LinkList L){//打印整张表 LNode *p; p=L->next; printf("该单链表元素为"); for(int j=0;j data); else printf("%d ",p->data); p=p->next; } } LNode *GetElem(LinkList L,int i){ if(i<1||i>length(L))return NULL; if(i==0)return L;//此处若i 的值为一返回L即表头节点 但在ListDelete()处失效 在失效处还需额外加上i==0的情况 int k=1; LNode *p=L->next; while(p&&knext; k++; } return p; } LNode *LocateElem(LinkList L,int e){ if(!L)return NULL; LNode *p=L; while(p){ if(p->data==e)break; p=p->next; } return p; } int ListInsert(LinkList L,int i,int e){//指定节点的后插操作 使用之前实现的GetElem()函数来找到第i-1个节点称之为*p节点,插入节点为*s if(i<1||i>length(L))return 0;//判断i的值是否合法 LNode* p=GetElem(L,i-1); LNode* s=(LNode*)malloc(sizeof(LNode)); s->data=e; s->next=p->next; p->next=s; return 1; } int forward_ListInsert(LinkList L,int i,int e){//单链表中通常采取后插法,当从表头按位查找到元素的复杂度为O(n)时对第i位的前插可以转化为对i-2位的后插 //此处是王道书上讲的依旧后插但是*p和*s的数据互换 if(i<1||i>length(L))return 0;//判断i的值是否合法 LNode* p=GetElem(L,i-1); LNode* s=(LNode*)malloc(sizeof(LNode)); s->data=p->data; s->next=p->next;//此处*s作为后插元素节点数据为 p->data p->next=s; p->data=e; //此处*p节点数据值为e return 1; } int ListDelete(LinkList L,int i){//按位删除元素值 if(i<1||i>length(L))return 0;//判定i的值是否合法 LNode *p; if(i==1) p=L; else p=GetElem(L,i-1); LNode *q=p->next; int e=q->data; p->next=p->next->next; free(q); printf("按值删除操作已完成nn"); return e; } void DestroyList(LinkList L){//依次由头节点删除并释放整张表 L=L->next; int i=1; while(L){ LNode*temp=L; printf("删除单链表中第%d个的元素,值为%dn",i,temp->data); L=L->next; free(temp); i++; } free(L); } int main() { LNode *temp; temp=List_HeadInsert(temp);//规定 //temp=List_Tail(L); PrintList(temp); printf("n"); printf("n"); printf("单链表长度为%dn",length(temp)); printf("n"); printf("该链表第三个元素为%dn",GetElem(temp,3)->data); printf("n"); printf("该链表的按值查找元素为%dn",LocateElem(temp,5)->data); printf("n"); if(Empty(temp))printf("这是个空的单链表");else printf("这是个非空的单链表n"); printf("n"); //ListInsert(temp,3,1216);//这里是索尔和查克的彩蛋 forward_ListInsert(temp,3,1216); PrintList(temp); printf("n"); printf("n"); ListDelete(temp,1); PrintList(temp); printf("n"); printf("n"); DestroyList(temp); return 0; }



