单链表上的一系列操作(基于c语言)

 单链表的实现分为两种单链表(其实差别并不是很大):带头结点和不带头结点,分别对应下面图中的上下两种。

链表的每一个结点是由两个域组成:数据域和指针域,分别存放所含数据和下一个结点的地址(这都是很明白的东西)

图中的东西可以分为三种:头指针llist;头节点info;正常的节点ki

下面定义结点的类型和单链表的类型:

struct Node;
typedef struct Node * PNode;
struct Node{
    DataType info;
    PNode link;
};
typedef struct Node * LinkList;
//很明显我们定义的结点指针类型和单链表的类型实际上是一样的东西
//后续的代码暂时与书上的内容保持一致,均使用有头结点的链表
//总结过后再将不带头结点的单链表实现补上

 

创建一个空链表:

LinkList creatNullList_link(void){
    LinkList llist = (LinkList)malloc(sizeof(struct Node));  //创建一个指向Node类型的指针llist
    if(llist != NULL)      llist->link = NULL;  //将其指向为空,也就是链表末尾
    else    printf("OUTOFSPACE!");
    return llist;    //看上面的代码后可知,llist可能为空,所以后面其他的函数经常会先判断了llist的情况
}

 

是否是空链表:

int isNullList_link(LinkList llist){
    return (llist->link == NULL);
}
//判断链表是否为空的代码比较简单

 

在链表中求第一个值为x的结点的存储位置:

PNode locate_link(LinkList llist,DataType x){
    PNode p;
    if (llist == NULL)    return NULL;  
    p = llist->link;
    while(p != NULL && p->info != x)    p = p->link;
    return p;
}
//为什么要判断llist是否为空而不是判断llist->link是否为空?
//如果llist为空,那使用llist->link不就是对一个空指针操作了吗,记得学指针的时候书上的一句话嘛,千万不要用没有初始化的指针,这里如果其指向为空,那llist->link也就不知道指向哪里

 

在p结点的后面插入一个值为x的新结点,返回是否插入成功的标志:

int insertPost_link(LinkList llist,PNode p,DataType x){
  PNode q = (PNode)malloc(sizeof(struct Node));
  if (q == NULL){
    printf("OUTOFSPACE");
    return 0;
  } 
  q->info = x;
  q->link = p->link;
  p->link = q;
  return 1;

}//下图为操作顺序,操作顺序不能反
//这一个方法是不需要用到llist

 

在p结点的前面插入值为x的新结点,返回插入成功与否的标志:

int insertPre_link(LinkList llist,PNode p,DataType x){
  PNode r;
  PNode q = (PNode)malloc(sizeof(struct Node));
  if(q == NUll){
    printf("OUTOFSPACE");
    return 0;
  }
  r = locatePre_link(llist,p);
  q->info = x;
  q->link = r->link;
  r->link = q;
  reutrn 1;
}
//找p结点的前驱结点
PNode locatePre_link(LinkList llist,PNode p){
  PNode p1;
  if (llist == NULL)  return NULL;
  p1 = llist;
  while(p1->link!=NULL && p1->link==p){
    p1 = p1->link;
  }
  reutn p1;
}
//感觉这个难一点的就是前驱结点的查找,p1->link!=NULL && p1->link == p是这个找前驱结点的灵魂

 

删除第一个元素内容为x的结点,返回删除成功与否的标志:

int deleteV_link(LinkList llist,DataType x){
  //不展示的方法:前面有一个定位方法,找到元素x的结点p,然后前面还有一个找前驱结点的方法,然后就可以执行删除操作了
  //下面是书上的方法
  PNode q,p;
  p = llist;
  if (p == NULL)  return 0;
  while(p->link!=NULL && p->link->info==x) p = p->link;
  //p是要删除结点的前驱结点
  if (p->link == NULL){
    printf("NOT EXIST!");
    return 0;
  }
  else{
    q = p->link;
    p->link = q->link;
    //也可以是p->link = p->link->link
    free(q);
    return 1;
  }
}

 

目前这基本上是书本上的代码示例了,后续会补充未给出的思考题,并且给出没有头结点时上述函数方法。

 

 

 

 

 

 

 

 

 

  • 添加到短语集
     
    • 没有此单词集:中文(简体) -> 英语...
       
    • 创建新的单词集...
  • 拷贝
  • 添加到短语集
     
    • 没有此单词集:中文(简体) -> 英语...
       
    • 创建新的单词集...
  • 拷贝
  • 添加到短语集
     
    • 没有此单词集:中文(简体) -> 英语...
       
    • 创建新的单词集...
  • 拷贝
  • 添加到短语集
     
    • 没有此单词集:中文(简体) -> 英语...
       
    • 创建新的单词集...
  • 拷贝
  • 添加到短语集
     
    • 没有此单词集:中文(简体) -> 英语...
       
    • 创建新的单词集...
  • 拷贝
  • 添加到短语集
     
    • 没有此单词集:中文(简体) -> 英语...
       
    • 创建新的单词集...
  • 拷贝
posted @ 2021-03-25 15:08  吃心王  阅读(259)  评论(0)    收藏  举报