zoukankan      html  css  js  c++  java
  • 数据结构之链表操作

          面试中单链表的相关操作也是常考的内容,本博文也是之前学习时的笔记,在此记录下来,以便日后用到,同时欢迎批评指正。

          一、基本操作 

          单链表的基本操作包括链表的创建、销毁、判空、索引、插入、删除等,下面是在链表的相关操作程序,链表的定义如下:

          typedef struct LNode{  

    int data;

    struct LNode *next;

    }LNode,*LinkList;

    此链表是带有头结点的,因此空链表的形式是 head->next=NULL .

           1. 链表的初始化

    LinkList InitList(void)    

    {
        LinkList head = NULL;
        head = (LinkList)malloc(sizeof(LNode));
        
        head->data = 0;
        head->next = NULL;    
        return head;    

    } 

            2.链表的销毁

     void DestoryList(LinkList L)        

    {
        LinkList pTemp = L->next,
            qTemp=L->next;
        if (L->next==NULL)                //此为空链表不需要再删除
            {
                printf("the list has already be empty!\n");
            }
         else{
               while(pTemp)
                {
                    qTemp = pTemp->next;
                    free(pTemp);
                    pTemp = qTemp;
                }
                L->next = pTemp;
            }
        }

            3.链表的判空

     bool ListEmpty(LinkList L)

    {
        if(L->next == NULL)
            {
                return TRUE;
            }
            else return FALSE;
    }    

            4.链表的长度

    int ListLength(LinkList L)                

        LinkList pTemp = L->next;
        int NodeCount = 0;
        for(;pTemp;pTemp = pTemp->next)
        {
            NodeCount++;
        }
        return NodeCount;

    } 

             5.链表的索引

    int GetElem(LinkList L,int i,int* e)        
    {                                //取出第i个节点
        LinkList pTemp = L;
        int j = 0;
        while(pTemp && j<i)
        {
            pTemp = pTemp->next;
            j++;
        }
        if(!pTemp || j>i)
            {
                printf("GetElem Error!\n");
                exit(0);
            }
        *e = pTemp->data;
    return *e;    

    } 

             6.链表的插入

    void Insert(LinkList L,int i,int e)
    {                                //在第i个节点插入e,因此需要找到第i-1节点,然后在其后插入
        LinkList Ins,
                pTemp = L;
        int j = 0;
        while(pTemp && j<i-1)
        {
            pTemp = pTemp->next;
            j++;
        }
        if(!pTemp || j>i-1)
            {
             printf("Error!\n");
             exit(0);
        }
        Ins = (LinkList)malloc(sizeof(LNode));
        if(Ins==NULL) printf("allocate memory error!\n");
        Ins->data = e;
        Ins->next = pTemp->next;
        pTemp->next = Ins;            

    } 

            7.链表的删除

    void Delete(LinkList L,int i,int e)
    {                                //删除第i个节点,因此找到第i-1节点,然后删除其后的节点
        LinkList Del,
                pTemp = L;
        int j = 0;
        while(pTemp->next && j<i-1)
        {
            pTemp = pTemp->next;
            j++;
        }
        if(!(pTemp->next) || j>i-1
            {
                    printf("error!\n");
                    exit(0);
            }    
        Del = pTemp->next;
        pTemp->next = Del->next;
        e = Del->data;
        free(Del);

    }

            8. 链表的创建

    该操作有两种方法,一种是头插法,另一种是尾插法

    void CreateList(LinkList &L,int n)

    {    //头插法,每次都是在链表的头部插入元素
        L = (LinkList)malloc(sizeof(LNode));
        if(L == NULL)
            {
                printf("error!");
                exit(0);
            }
        L->next=NULL;
        for( i=0;i<n;i++)
        {
            p = (LinkList)malloc(sizeof(LNode));
            scanf(&p->data);
            p->next=L->next;
            L->next = p;
        }

    } 

    void CreateList(LinkList &L,int n)
    {  //尾插法,每次都是从链表的尾部插入元素,最后把链表的next指针赋值为NULL
        L = (LinkList)malloc(sizeof(LNode));
        if (L == NULL) 
        {
            printf("error!");
            exit(0);
        }
        L->next = NULL;
        pre = L;
        for(i=0;i<n;i++)
        {
            p = (LinkList)malloc(sizeof(LNode));
            scanf(&p->data);
            pre ->next = p;
            pre = p;
        }
        pre->next = NULL;

    } 

             二、其他操作

            1.链表的反转

    ListList ReverseList(LinkList L )

    {  //带有头结点,p为L的第一个元素
        LinkList p = L->next;
        LinkList prev = NULL,temp = NULL;
        while(p!=NULL)
        {
            temp = p;
            p = p->next;
            temp->next = prev;
            prev = temp;
        }
        L->next = prev;
        return L;

    } 

    链表的反转也可以使用递归来做! 

    2.删除一个元素x

    ListList ReverseList(LinkList L )
    {  //带有头结点,p为L的第一个元素
        LinkList p = L->next;
        LinkList prev = NULL,temp = NULL;
        while(p!=NULL)
        {
            temp = p;
            p = p->next;
            temp->next = prev;
            prev = temp;
        }
        L->next = prev;
        return L;

    } 

    3.删除所有重复的元素

     void DeleteAllX(LinkList L)

    {
        LinkList p = L,
                 pPrev,
                 pCurr;
        while( p!= NULL)
        {
            pPrev = p;
            pCurr = p->next;
            while(pCurr != NULL)
            {
                if(pCurr->data == p->data)
                    {
                        pPrev->next = pCurr->next;
                        free(pCurr);
                        pCurr = pPrev->next;
                    }
                else
                    {
                        pPrev = pCurr;
                        pCurr = pCurr->next;
                    }
            }
            p = p->next;
        }
    }

      4.判断链表是不是有环

    Bool IsLoop(LinkList head)
    {
        LinkList slow = head,
                         fast = head;
        while(fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
            if(slow == fast)
                break;
        }
        return !(fast == NULL || fast->next == NULL);

    } 

      如果链表带环的话,找出环的入口,这个原理网上有介绍,算法也一大堆!

      5.将链表分为两个链表,一个为奇数序的元素,另一个为偶数序的元素

    void splice(LinkList La, LinkList Lb)
    {
        LinkList Lb,pb,pa,pTemp;
        Lb = (LinkList)malloc(sizeof(LNode));
        pa = La->next;
        pb = Lb;
        while(pa->next)
        {
            pTemp = pa->next;
            pa->next = pTemp->next;
            pb->next = pTemp;
            pb = pTemp;
            pa = pa->next;
        }
        pb->next = NULL;

    } 

      6.单链表的插入排序

    void InsertSort(LinkList L)
    {
        LinkList p,q,pre,r;
        
        p = L->next;
        while(p->next)
        {
            q = p->next;
            if(q->data < p->data)
                {
                    pre = L;
                    r = L->next;
                    while(r!=p && r->data < q->data)
                    {
                        pre = r;
                        r = r->next;
                    }
                  p->next = q->next;
                  q->next = r;
                  pre->next = q;
                }
            else
                p = p->next;
        }

    } 

      7.单链表的选择排序

     void SelectSort(LinkList L)

    //r总是指向最小的节点
        LinkList p,q,r;
        p = L->next;
        while(p->next)
        {
            r = p;
            q = p->next;
            while(q)
            {
                if(r->data > q->data)
                     r = q;
                q = q->next;
            }
            if(r != p)
                {
                    temp = p->data;
                    p->data = r->data;
                    r->data = temp;
                }
            p = p->next;
        }
    }
  • 相关阅读:
    LeetCode Binary Tree Inorder Traversal
    LeetCode Populating Next Right Pointers in Each Node
    LeetCode Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode Reverse Linked List II
    LeetCode Populating Next Right Pointers in Each Node II
    LeetCode Pascal's Triangle
    Palindrome Construct Binary Tree from Preorder and Inorder Traversal
    Pascal's Triangle II
    LeetCode Word Ladder
    LeetCode Binary Tree Zigzag Level Order Traversal
  • 原文地址:https://www.cnblogs.com/kingcucumber/p/2872552.html
Copyright © 2011-2022 走看看