单链表的创建及相关算法

# include<stdio.h>
# include<malloc.h>

typedef struct node{
  int data;
  struct node *next;
}node,*pnode;;
int n;/*初始节点数目*/
pnode creatlist();/*创建一个链表*/
void showlist(pnode phead);/*输出链表*/
void list_pushback(pnode phead,int val);/*尾插法插入一个值*/
void list_pushfront(pnode phead,int val);/*头插法插入一个值*/
void list_popback(pnode phead);/*删除尾部的一个值*/
void list_popfront(pnode phead);/*删除头部的一个值*/
bool list_insert(pnode phead,int pose,int val);/*在pos位置之后插入一个值*/
bool list_erase(pnode phead,int pose);/*删除pos位置的值*/
void list_remove(pnode phead,int val);/*删除值为val的节点*/
void list_destory(pnode phead);/*删除整个链表*/
int list_find(pnode phead,int val);/*查找是否存在值为val的点,存在返回该指针,否则返回NULL*/
bool list_isempty(pnode phead);/*链表是否为空*/

int main(){
  printf("请输入节点数目:");
  scanf("%d",&n);

  pnode phead = (pnode)malloc(sizeof(node));
  phead = creatlist();
  showlist(phead);

  printf("请输入要在尾部插入的值:");
  int val;
  scanf("%d",&val);
  list_pushback(phead,val);
  showlist(phead);

  printf("请输入要在头部插入的值:");
  scanf("%d",&val);
  list_pushfront(phead,val);
  showlist(phead);

  printf("请输入你想要在哪个位置后插入哪个值\n");
  printf("pose:");
  int pose;
  scanf("%d",&pose);
  printf("val:");
  scanf("%d",&val);
  list_insert(phead,pose,val);
  showlist(phead);

  printf("请输入你要删除的节点位置");
  scanf("%d",&pose);
  list_erase(phead,pose);
  showlist(phead);

  printf("请输入你要删除的值");
  scanf("%d",&val);
  list_remove(phead,val);
  showlist(phead);
  
  printf("\n");
  list_destory(phead);
  showlist(phead);
  printf("\n请输入你要查询的值:");
  scanf("%d",&val);
  int loc = list_find(phead,val);
  printf("%d",loc);
  return 0;
}
pnode creatlist(){
  pnode phead = (pnode)malloc(sizeof(node));/*创建头指针指向第一个节点*/
  pnode ptail = phead;/*ptail用于不断后移创建新的节点*/
  ptail->next = NULL;
  int val;
  printf("请输入节点的值");
  for(int i = 1;i <= n;++i){
  scanf("%d",&val);/*节点值*/

  pnode pnew = (pnode)malloc(sizeof(node));/*创建一个新的节点*/
  pnew->data = val; /*将新节点的值写为val*/
  ptail->next = pnew;/*当前节点的下一个节点为新节点*/
  pnew->next = NULL;/*新节点的下一个为空*/
  ptail = pnew;/*ptail指向新的节点*/
  }
  return phead;/*返回头节点的地址*/
}

void showlist(pnode phead){
  pnode ptail = phead->next;/*ptail指向链表的第一个节点*/
  while(ptail != NULL)/*当尚未遍历到链表的尾端时*/
  {
    printf("%d ",ptail->data);/*输出节点的值*/
    ptail = ptail->next;/*移动到下一个节点*/
  }  
  return;
}
void list_pushback(pnode phead,int val){
  pnode ptail = phead;/*新建一个指针指向头节点*/
  while(ptail ->next!= NULL) ptail = ptail->next;/*不断向后遍历直到链表的尾端*/
  pnode pnew = (pnode)malloc(sizeof(node));/*新建一个新节点*/
  pnew->data = val;/*新节点的值为要插入的值*/
  pnew->next = NULL;/*新节点的下一个为空*/
  ptail->next = pnew;/*链表尾端指向新节点,也就是插入一个新的节点*/
}

void list_pushfront(pnode phead,int val){
  pnode ptail = phead;/*指向头节点*/
  pnode pnew = (pnode)malloc(sizeof(node));/*新建一个节点*/
  pnew ->data = val;/*新节点的值为val*/
  pnew->next = ptail->next;/*新节点的下一个为头节点的下一个*/
  ptail->next = pnew;/*头节点的下一个指向新节点*/
  /*
    这里比较难理解的就是头插的过程,用数字模拟一下如下:
    1 2 3(原链表)
    ptail ptail->next

    4(新节点)pnew
    pnew->next = ptail->next; 4指向了2,此时1仍然指向2
    ptail->next = pnew; 1指向4
    整个链表变为:
    1 4 2 3
    ptail ptail->next
    pnew pnew->next
    这里只演示头插法的过程,真正的phead实际指向了一个值为空的节点
  */
}
bool list_insert(pnode phead,int pose,int val){
  int i = 0;/*定位*/
  pnode ptail = phead;
  while(i < pose && ptail!=NULL){
  ptail = ptail->next;/*不断向后遍历直到到达pose位置*/
  i++;/*定位器后移*/
  }
  if(i < pose) return false;/*如果i < pose说明没有Pose这个节点*/
  pnode pnew = (pnode)malloc(sizeof(node));
  pnew ->data = val;
  pnew->next = NULL;
  pnew->next = ptail->next;
  ptail->next = pnew; /*头插法同上*/
  return true;
}
bool list_erase(pnode phead,int pose){
  int i = 0;/*定位*/
  pnode ptail = phead;
  while(i < pose-1 && ptail!=NULL){
  ptail = ptail->next;/*不断向后遍历直到到达pose-1位置*/
  i++;/*定位器后移*/
}
  if(i < pose-1) return false;/*如果i < pose说明没有Pose-1这个节点*/
  pnode p = ptail->next;/*新建一个指针指向要删除的节点Pose*/
  ptail->next = p->next;/*待删节点的前一个节点指向待删节点后的一个节点*/
  free(p);/*释放待删节点,删除节点*/
  return true;
}
void list_remove(pnode phead,int val)
{
  pnode ptail = phead->next;/*ptail指向第一个节点*/
  pnode p = phead;/*p指向ptail的前一个位置*/
  if(ptail == NULL) return;
  while(ptail!=NULL)

  {
    if(ptail->data == val)/*如果ptail的值为val*/
    {
      p->next = ptail->next;/*ptail前的点指向ptail后的点*/
      free(ptail);/*释放ptail,既删除值为val的节点*/
      ptail = p->next;/*ptail复原指向链表*/
    }
    else

    {
      ptail = ptail->next;/*ptail指向下一个节点*/
      p = p->next;/*p向前跟上ptail*/
    }
  }
}
void list_destory(pnode phead){
  pnode ptail = phead->next;/*指向第一个节点*/

  pnode p =phead;/*指向ptail的前一个节点(头节点)*/
  phead = NULL;
  if(ptail == NULL)/*如果第一个节点为空*/
  {
    free(p);/*释放头节点*/
    return;
  }
  while(p != NULL)
  {
    free(p);/*释放节点*/
    p = ptail;/*p向前移动*/
    ptail = ptail->next;/*ptail向前移动*/
  }
  return;
}
int list_find(pnode phead,int val)
{
  int ans = 0;/*记位器*/
  pnode ptail = phead;
  while(ptail != NULL && ptail->data != val)/*如果尚未遍历到链表尾并且当前节点的值不为val就继续查询*/
  {
    ans++;
    ptail = ptail->next;
  }

  if(ptail == NULL) return -1;/*ptail指向空说明整个链表里没有值为val的节点*/

  else return ans;/*返回位置*/
}
bool list_isempty(pnode phead){
  pnode ptail = phead->next;
  if(ptail != NULL) return false;/*如果第一个节点不为空则链表非空*/
  else return true;
}

posted @ 2022-03-02 19:49  empty_y  阅读(202)  评论(0)    收藏  举报