链表

来源:互联网 发布:python return 空 编辑:程序博客网 时间:2024/06/03 14:25

也许迷途的惆怅
会折碎我的脚步
可我相信未来
会给我一双梦想的翅膀
虽然失败的苦痛
已让我遍体鳞伤
可我坚信光明就在远方
我用翅膀掀起那天边的排浪
我用身躯托起那血红的太阳
就在这刺骨而凛冽的大风中
你会听到我赞美未来的呼喊
也许征程的迷惘
会折碎我的手臂
可我相信未来
会给我一双梦想的翅膀
虽然挫折的创伤
已让我寸步难行
可我坚信光明就在远方
可我坚信光明就在远方
—原唱汪峰《光明》(可我喜欢的是罗京民版——沧桑、和数十年对人生的感悟)


关于Status InitList(LinkList *L)的问题详情参见 C语言函数传递指针参数的问题
函数中改变变量的内容就要找到它的地址
现在的问题是LinkList L;这条语句怎么实现的(给L开辟了一个怎样的空间,空间大小,空间里的值是什么);
当运行DestoryList(&L)后L又变成了什么?

单链表

头文件、宏定义、存储结构

 /* c1.h (程序名) */ #include<string.h> #include<ctype.h> #include<malloc.h> /* malloc()等 */ #include<limits.h> /* INT_MAX等 */ #include<stdio.h> /* EOF(=^Z或F6),NULL */ #include<stdlib.h> /* atoi() */ #include<io.h> /* eof() */ #include<math.h> /* floor(),ceil(),abs() */ #include<process.h> /* exit() */ #include<conio.h> /* 函数结果状态代码 */ #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */ typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */typedef int ElemType;//将整型作为数据元素//单链表struct LNode {   ElemType data;   struct LNode *next; }; typedef struct LNode *LinkList; typedef struct LNode LNode;

改变L内容的InitList、DestoryList

 Status InitList(LinkList *L)//改变L的内容 { // 操作结果:构造一个空的线性表L   *L=(LinkList)malloc(sizeof(struct LNode)); //产生头结点,并使L指向此头结点   if(!*L) //存储分配失败     exit(OVERFLOW);   (*L)->next=NULL; //指针域为空   return OK; } Status DestroyList(LinkList *L)//改变L的内容 {  //释放包括头节点的所有节点       LinkList q;       while(*L)       {           q=(*L)->next; //先保存下一个节点的地址,把当前节点释放(不然找不到下一个节点)           free(*L);           *L=q;       }       return OK; }

ClearList、ListEmpty、ListLength

Status ClearList(LinkList L) {  //释放除头节点外的节点     LinkList p,q;     p=L->next;     while(p) //因为是释放当前节点,所以判断当前节点是否为空     {         q=q->next;         free(p);         p=q;     }      L->next=NULL;      return OK; } Status ListEmpty(LinkList L) {//判断L是否为空表(只有头节点)空表返回TRUE,否则返回FALSE     if(L->next)        return TRUE;     else        return FALSE; } int ListLength(LinkList L) {  //返回数据元素个数       int i=0;       LinkList p;       p=L->next;       while(p)       {//当前节点不为空计数器加一           i++;           p=p->next;       }       return i; }

GetElem、LocateElem、PriorElem、NextElem

Status GetElem(LinkList L,int i,ElemType *e)//这里的ElemType指的是链表单元的数据类型 { //查找第i个位置的数据元素,弱存在其值付赋给e,返回OK     LinkList p;     p=L->next;//从首元结点开始     int j=1;//计数器开始为 1     while(p&&j<i)//顺着指针查找,未找到前当前节点为空自然退出     { //这里说一下为啥(j<i)       //如果改成j<=i;当循环到j=i时,跳出循环后p指向的是i+1节点         p=p->next;         j++;     }     //跳出循环后p指向的就是第i个节点     if(!p||j<i)//第i个元素     return ERROR;     *e=p->data;     return OK; }Status equal(ElemType c1,ElemType c2){    if(c1==c2)        return TRUE;    return FALSE;} int LocateElem(LinkList L,ElemType e,Status (*compare)(ElemType,ElemType)) { //通过比较确定数据元素位置 ,找到返回数据元素位置,不然返回0         int i=0;         LinkList p=L->next;//从首元节点开始比较         while(p)         { //当前节点不为空计数器加一               i++;               if(compare(p->data,e))               return i;         }         return 0; }Status PriorELem(LinkList L,ElemType cur_e,ElemType *pre_e){    LinkList p,q;    p=L->next; //首元结点必然不能是目标节点               //首元结点必然要有直接后继,这是while初始条件    while(p->next)    {        q=p->next;//p保留当前节点q的直接前驱,        if(q->data==cur_e)        {            *pre_e=q->data;            return OK;        }        p=q;    }    return INFEASIBLE;}Status NextElem(LinkList L,ElemType cur_e,ElemType *next_e){ //返回目标节点的直接后继,不用额外变量保留上一节点信息    LinkList p=L->next;    while(p->next)    {        if(p->data==cur_e)        {            *next_e=p->next->data;            return OK;        }        p=p->next;    }    return INFEASIBLE;}

ListInsert、ListDelete、ListTraverse

Status ListInsert(LinkList L,int i,ElemType e){    LinkList p,s;    p=L;//    int j=0;    if(i<1||i>ListLength(L)+1) //插入位置不合理      return ERROR;    while(p&&j<i-1)    {//插入位置是i-1后面     //循环条件是当前节点不为空且指针位置未到i-1     p=p->next;     j++;    }    //跳出循环p指向i-1节点    s=(LinkList)malloc(sizeof(struct LNode));    if(!s)        exit(OVERFLOW);    s->data=e;    //注意指针改变的顺序    s->next=p->next;    p->next=s;    return OK;}Status ListDelete(LinkList L,int i,ElemType *e){//找到第i-1节点的位置,释放第i个节点    LinkList p=L;    int j=0;    if(i<0||i>ListLength(L))//不能删除第0个节点以及第n+1个节点        return ERROR;    while(p->next&&j<i-1)    {        j++;        p=p->next;    }     LinkList q=p->next;     p->next=q->next;     *e=q->data;    free(q);     return OK;} void Printf(ElemType e) {     printf("%d ",e); }Status ListTraverse(LinkList L,void (* vi)(ElemType)){    LinkList p=L->next;    while(p)    {        vi(p->data);        p=p->next;    }    printf("\n");    return OK;}

循环双链表

typedef int ElemType;//将整型作为数据元素struct LNode {   ElemType data;   struct LNode *next;   struct LNode *prior; }; typedef struct LNode *DuLinkList; typedef struct LNode DuLNode;  Status InitList(DuLinkList *L) {//头指针尾指针都指向自己   *L=(DuLinkList)malloc(sizeof(struct LNode));   if(!*L)     exit(OVERFLOW);     //空表的象征是next、prior都指向L   (*L)->next=*L;   (*L)->prior=*L ;   return OK; } Status DestoryList(DuLinkList *L) {//释放所有内存     DuLinkList p,q;     p=(*L)->next;     while(p!=*L)//由于是循环链表尾节点的next指向头节点     {         q=p->next;         free(p);         p=q;     }     free(*L);     *L=NULL;     return OK; } Status ClearList(DuLinkList L) { //空表的象征是next、prior都指向L     DuLinkList p,q;     p=L->next;     while(p!=L)     {         q=p->next;         free(p);         p=q;     }     L->next=L;     L->prior=L; } Status ListEmpty(DuLinkList L) {//空表的象征是next、prior都指向L     if(L->next==L&&L->prior==L)        return TRUE;     return FALSE; } int ListLength(DuLinkList L) {     int i=0;     DuLinkList p;     p=L->next;     while(p!=L)     {         i++;         p=p->next;     }     return i; } Status GetElem(DuLinkList L,int i,ElemType *e) {     int j=1;//表示节点序号从1开始     if(i<1||i>ListLength(L))        return ERROR;     DuLinkList p;     p=L->next;     while(p!=L&&j<i)     { //循环结束指针指向第i个元素         j++;         p=p->next;     }     *e=p->data;     return OK; } int LocateElem(DuLinkList L,ElemType e,Status(*compare)(ElemType,ElemType)) {     int i=0;     DuLinkList p;     p=L->next;     while(p!=L)     {         i++;         if(compare(p->data,e))            return i;         p=p->next;     }     return 0; } Status PriorElem(DuLinkList L,ElemType cur_e,ElemType *pre_e) {     DuLinkList p,q;     p=L->next->next;     while(p!=L)//未到表头     {        if(p->data==cur_e)            {                *pre_e=p->prior->data;               return TRUE;           }         p=p->next;     }     return FALSE; }  Status NextElem(DuLinkList L,ElemType cur_e,ElemType *next_e) {     DuLinkList p,q;     p=L->next;     while(p->next!=L)//p的下一个节点不是表头     {        if(p->data==cur_e)            {                *next_e=p->next->data;               return TRUE;           }         p=p->next;     }     return FALSE; } Status ListInsert(DuLinkList L,int i,ElemType e) {     int j=1;     if(i<1||i>ListLength(L)+1)        return ERROR;     DuLinkList p,q,s;     p=L->next;     while(p!=L&&j<i)     p=p->next;     s=(DuLinkList)malloc(sizeof(DuLNode));     if(!s)        return OVERFLOW;     s->data=e;     q=p->prior;     q->next=s;     s->prior=q;     s->next=p;     p->prior=s;     return OK; } Status ListDelete(DuLinkList L,int i,ElemType *e) {   DuLinkList p,q;   if(i<1||i>ListLength(L))     return ERROR;     p=L->next;     int j=1;   while(p!=L&&j<i)    {        j++;        p=p->next;    }   *e=p->data;  q=p->prior;  q->next=p->next;  p->next->prior=q;  free(p);   return OK; } void Printf(ElemType e) {     printf("%d ",e); } void ListTraverse(DuLinkList L,void(*visit)(ElemType)) { // 由双链循环线性表L的头结点出发,正序对每个数据元素调用函数visit()   DuLinkList p=L->next; /* p指向头结点 */   while(p!=L)   {     visit(p->data);     p=p->next;   }   printf("\n"); } void ListTraverseBack(DuLinkList L,void(*visit)(ElemType)) { // 由双链循环线性表L的头结点出发,逆序对每个数据元素调用函数visit()。   DuLinkList p=L->prior; /* p指向尾结点 */   while(p!=L)   {     visit(p->data);     p=p->prior;   }   printf("\n"); }