本篇博客主要介绍链表的操作,较上次的链表题难,更能够锻炼C语言的编程能力,对以后的面试有很大的帮助。内容主要包括单链表实现约瑟夫环,链表的排序,合并两个有序链表,判断链表是否带环并且计算环的长度等问题。


       建立链表节点:

typedef int Datatype;
typedef struct SListNode
{
     Datatype Data;
     SListNode *next;
}SListNode;


——下面主要具体的程序实现(注释对代码的理解)

//链表的基本操作2
//单链表实现约瑟夫环
SListNode * JoseCycle(SListNode * pHead, int k)
{
     if (pHead == NULL)    //先进行链表判空操作
     {
         return NULL;
      }
     SListNode *cur = pHead;
     while (1)
     {
        if (cur->next == cur)    
        {
            return cur;
        }
        int count = k-1;     //执行k-1次
        while (count--)
        {
            cur = cur->next;
         }
      //替换法进行删除
        SListNode *next = cur->next;
        cur->Data = next->Data;
        cur->next = next->next;
        free(next);
     }
}

//单链表的冒泡排序
void BubbleSort(SListNode *pHead)
{
     if (pHead == NULL || pHead->next == NULL)
     {
         return ;
     }
     SListNode *tail = pHead;
     while (tail)    //使用两次循环进行冒泡控制
     {
         SListNode *cur = pHead;
         SListNode *next = pHead->next;
         while (next)
        {
            if (cur->Data > next->Data)
            {
                Datatype tmp = cur->Data;
                cur->Data = next->Data;
                next->Data = tmp;
                cur = cur->next;
                next = next->next;
            }
            tail = tail->next;
        }
    }
}

//合并两个有序单链表,使得链表仍有序
SListNode *MergeList(SListNode * L1, SListNode *L2)
{
     if (L1 == NULL)    //先考虑L1和L2为空的情况,进行处理
     {
         return L2;
     }
     if (L2 == NULL)
     {
         return L1;
     }
     SListNode * newHead;    //创建新的链表
     SListNode *pHead1 = L1;
     SListNode *pHead2 = L2;
     if (pHead1->Data < pHead2->Data)    //确定新链表的头节点
     {
         newHead = pHead1;
         pHead1 = pHead1->next;
      }
     else
     {
         newHead = pHead2;
         pHead2 = pHead2->next;
      }
     SListNode *tail = NULL;
     while (pHead1 && pHead2)   //将两个指针指向的内容相比较,摘掉较小的连接到新的链表中
     {
         if (pHead1->Data < pHead2->Data)
         {
             tail->next = pHead1;
         }
         else
         {
             tail->next = pHead2;
             pHead2 = pHead2->next;
         }
         tail = tail->next;
     }
     if (pHead1)     //将另一个有剩余节点的链表,直接连接到新的链表上
     {
         tail->next = pHead1;
     }
     else if (pHead2)
     {
         tail->next = pHead2;
     }
     return newHead;
}

//释放节点
void DestoryList(SListNode *pHead)
{
     SListNode *cur = pHead;
     while (cur)
    {
         SListNode *tmp = cur;
         cur = cur->next;
         free(tmp);
     }
     pHead = NULL;
}

//判断链表是否带环?求环的长度?
SListNode *checkCycle(SListNode *pHead)
{
     SListNode *slow = pHead;   //利用快慢指针的方式
     SListNode *fast = pHead;
     while (fast && fast->next)
     {
         slow = slow->next;
         fast = fast->next->next;
         if (fast == slow)    //若快指针和慢指针相遇,则链表中带环
         {
             return fast;
          }
      }
     return NULL;
}

//求环的长度
int GetCycleLength(SListNode *ptr)
{
     assert(ptr);        //先对指针进行判空
     SListNode *cur = ptr;
     int count = 0;
     do
     {
         ++count;
         cur = cur->next;
     } while (cur != ptr);   //利用计数器的方式进行计数
     return count;
}