双向非循环链表(没有头结点)

双向非循环链表:虽然没有设置表头,其实是把第一个结点当做头结点来处理的。分别实现了:初始化链表、创建链表、从尾部插入链表、获取指定位置结点的值、从头开始遍历链表、给定结点指针分别向前和向后遍历、删除给定位置结点


/*双向非循环链表、无表头*/
#include<stdio.h>
#include<stdlib.h>
typedef struct NODE{
    struct NODE *prev;    //指向前一个结点
    struct NODE *next;    //指向后一个结点
    int         value;    //当前结点值
}Node;

void InitList(Node *Plist)
{
 Plist = NULL;
 printf("InitList is succed!\n");
}

Node *CreateList(Node *Plist)
{
 printf("CreateList start!\n");
 Node *Pinsert;//要插入的结点
 Node *Plast;//指向最后一个结点
 Pinsert = (Node *)malloc(sizeof(Node));
 if(Pinsert == NULL)
 {
  return NULL;
 }
 
 Plast = Plist;
 printf("Please input the value you want to insert:");
 scanf("%d",&Pinsert->value);
 if(Pinsert->value < 0)
  {
   printf("the value is illegal\n");
   return NULL;
  }
 while(Pinsert->value > 0)
  {
   if(Plist == NULL)
    {
     Plist = Pinsert;
     Plast = Plist;
    }
   else
    {
     Plast->next = Pinsert;
     Pinsert->prev = Plast;
     Plast = Plast->next;   //Plast移到下一个结点
    }
   //继续插入新的结点
   Pinsert = (Node *)malloc(sizeof(Node));
   if(Pinsert == NULL)
    {
     return NULL;
    }
   scanf("%d",&Pinsert->value);
  }
 printf("CreateList end!\n");
 return Plist;
}
//在链表尾部插入新结点
int InsertList(Node *Plist,int item)
{
 Node *Newnode;
 Node *Curnode;
 Newnode = (Node *)malloc(sizeof(Node));
 if(Newnode == NULL)
  {
   return -1;
  }
 Curnode = Plist;
 Newnode->value = item;
 if(Curnode == NULL)  //空链表的情况
  {
   Plist = Newnode;
   return 0;
  }

 while(Curnode->next != NULL)
  {
   Curnode = Curnode->next;
  }
 Curnode->next = Newnode;
 Newnode->prev = Curnode;
 
 return 0;
}
//查找指定位置的结点,返回该结点的值
int Getelement(Node *Plist,int position)
{
 printf("Getelement start!\n");
 Node *Curnode;
 int i = 1;
 Curnode = Plist;
 while(Curnode != NULL)
  {
   if(i == position)
    {
     printf("%d",Curnode->value);
     printf("\nGetelement end!\n");
     return 0;
    }
   Curnode = Curnode->next;
   i++;
  }
 printf("can not find the element!");
 printf("Getelement end!\n");
 return -1;
}
//从第一个结点开始遍历到最后
int PrintList(Node *Plist)
{
 printf("PrintList start!\n");
 if(Plist == NULL)
  {
   printf("the LinkList is null\n");
  }
 else
  {
   while(Plist != NULL)
   {
    printf("%d  ",Plist->value);
    Plist = Plist->next;
   }
  }
 printf("\n");
 printf("PrintList end!\n");
 return 0;
}

//给定结点指针分别往前后遍历
int TraList(Node *GiveNode)
{
 Node *Prevnode;
 Node *Nextnode;
 Prevnode = GiveNode;
 Nextnode = GiveNode;
 printf("TraList start!\n");
 if(Prevnode == NULL)
  {
   printf("the LinkList is null\n");
  }
 else
  {
   printf("Traverse backwards:\n");
   while(Prevnode != NULL)
   {
    printf("%d  ",Prevnode->value);
    Prevnode = Prevnode->prev;
   }
   printf("\n");
   printf("Traverse forward:\n");
   while(Nextnode != NULL)
   {
    printf("%d  ",Nextnode->value);
    Nextnode = Nextnode->next;
   }
  }
 printf("\n");
 printf("TraList end!\n");
 return 0;
}

//删除指定位置结点
int DeleteList(Node *Plist,int position)
{
 Node *Delnode;
 int i = 1;
 
 printf("DeleteList start!\n");
 
 Delnode = Plist;
 while(Delnode != NULL)
  {
   if(i == position)
    {
     Delnode->next->prev = Delnode->prev;
     Delnode->prev->next = Delnode->next;
     
     free(Delnode);
     printf("DeleteList end!\n");
     return 0;
    }
   Delnode = Delnode->next;
   i++;
  }
 printf("can not find the element!");
 printf("DeleteList end!\n");
 return 0;
}


int main()
{
 printf("main bgein!\n");
 Node *Plist;
 Node *GiveNode;
 int item;

 InitList(Plist);
 
 Plist = CreateList(Plist);
 PrintList(Plist);   //打印全部结点
 
 printf("please input a item you want to insert:");
 scanf("%d",&item);
 InsertList(Plist,item);  //插入结点
 PrintList(Plist);
 
 Getelement(Plist,3);
 
 DeleteList(Plist,5);
 PrintList(Plist);
 
 GiveNode = Plist->next->next;
 TraList(GiveNode);     //按给定结点分别向前向后遍历
 
 printf("main end!\n");
 return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
约瑟夫问题是经典的数学游戏,也称为约瑟夫环,由于其富有趣味性和一定的数学难度而被广泛研究和应用。解决约瑟夫问题的方法有多种,其中一种常用方法是使用双向循环链表头结点双向循环链表是一种特殊的链表,它可以遍历整个链表,即尾节点的下一个结点是头结点头结点的上一个结点是尾节点,这样形成的链表称为双向循环链表。带头结点双向循环链表头结点前面加入一个空结点,使得空结点也能对链表中结点进行操作。 在解决约瑟夫问题时,我们首先需要初始化双向循环链表,然后按照一定规则进行出队操作,直到只剩下最后一个结点为止。假设约瑟夫问题中有n个人围成一圈,从第k个人开始报数,报到第m个人就将其出队,然后从下一个人重新开始报数,求最后留下的人的编号。 具体实现时,我们可以根据输入的n和k创建双向循环链表,并从头结点开始依次插入n个结点,然后设置m的值并从头结点开始不断遍历链表直到只剩下一个结点。在遍历过程中,每经过m个结点就将该结点从链表中删除,并将该结点的下一个结点作为新的起点继续报数。最后剩下的那个结点即为答案。 总之,使用双向循环链表头结点解决约瑟夫问题可以简化求解过程,提高代码效率和可读性,是一种比较常用的数据结构和算法应用方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值