zoukankan      html  css  js  c++  java
  • 王道数据结构代码:单链表的操作

    带头节点的

    ListInsert(LinkList &L , int index , ElemType e):实现数据的插入

    ListIndexNextInsert(LNode *p , ElemType e):指定节点后插入数据

    ListIndexPriorInsert(LNode *p , ElemType e):指定节点前插入数据

    ListDelete(LinkList &L , int index , ElemType &e):删除指定位序的节点,并返回节点元素

    ListDeletePoint(LNode *p):删除指定节点

    GetElem(LinkList L , int index):查找指定位序的节点

    LocateElem(LinkList L , ElemType e):按值查找

    ListLenght(LinkList L):求链表的长度

    List_TailInsert(LinkList &L):头插法创建链表

    List_HeadInsert(LinkList &L):尾插法创建链表

    fanzhuanList(LinkList &L):反转(逆置)链表

    Init():初始化链表

    bianliList(LinkList L):遍历链表

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    #define ElemType int
    typedef struct LNode{
        ElemType data ; // 我这里用的是Int型的数据
        struct LNode *next; 
    }LNode , *LinkList;// 创建节点
    
    LNode * GetElem(LinkList L , int index); 
    bool ListIndexNextInsert(LNode *p , ElemType e);
    bool ListInsert(LinkList &L , int index , ElemType e){ // 插入 
        if(index < 1)
            return false;
        LNode *p = L; // 指向头节点 
        int j = 0 ;
        while(p != NULL && j < index-1){ // 插入位序的前一个 
            p = p->next;
            j++; 
        } 
        //上面的 这段代码可以用GetElem代替,封装,下面写的查找函数 
        /*
        王道视频说可以用GetElem还查找p节点,这样子是不行的,视频用的是下面这一行语句
        LNode *p = GetElem(L , index-1); 
        我们来走一下,我向插入的是index = 1 , index - 1 = 0 
        , GetElem 中有 if(i < 1) return false;  这里有问题了,会导致数据不能再第一个节点插入 
            如果想改的话,要动一些东西 
        */  
         /*
        if(p == NULL)
            return false;
        /* 
        下面的代码可以用这个来代替*/ 
            //ElemType i = index ;
            return ListIndexNextInsert(p,index);
            /// 封装了 
        
        /*if(p == NULL) // 走到头了 
            return false;
        LNode *s = (LNode*)malloc (sizeof(LNode)); // 为插入的数据申请一个内存地址
        s->data = e ;
        s->next = p->next;
        p->next = s;
        return true;*/
    }    
    
    bool ListIndexNextInsert(LNode *p , ElemType e){ // 指定的节点后插入数据 ,指定的节点 P  
        if(p == NULL)
            return false;
        LNode *s = (LNode*)malloc(sizeof(LNode));
        s->data = e;
        s->next = p->next;
        p->next = s;
        return true;
    } 
    bool ListIndexPriorInsert(LNode *p , ElemType e){//指定的位置前插入数据
        if(p == NULL)
            return true;
        // 先把节点插入在P节点的后面 , 在交换这连个结点的数据 
        LNode *s = (LNode*)malloc(sizeof(LNode));
        s->data = e ;
        s->next = p->next;
        p->next = s;
        
        // 交换数据 
        ElemType temp = s->data;
        s->data = p->data;
        p->data = temp; 
        return true;
    }
    bool ListDelete(LinkList &L , int index , ElemType &e){/// 带头节点的 
        // e 是返回被删除的元素
        if(index < 1)
            return false;
        int j = 0 ;
        LNode *p = L;
        while(p != NULL && j < index-1){
            p = p->next ;
            j++;
        } 
        if(p == NULL||p->next == NULL) // 这里要注意一下后面这个判断条件,可以画图理解一下 
            return false;
        LNode *q = p->next; // 指向被删除的节点
        e = q->data;
        p->next = q->next;
        free(q);
        return true;
    }
    bool ListDeletePoint(LNode *p){ // 删除指定节点 
        if(p == NULL) 
            return true ;
        // 实质是把p节点的下一个节点的删除,把下一个节点的数据复制到P节点上来 
        // 如果删除的节点是链表的最后一个节点,就会出错, 
        //解决办法是传入链表的第一个节点,重头遍历过来  , 这样写其实也可以了的 
        LNode *q = p->next;
        p->data = q->data;
        p->next = q->next;
        free(q);
        return true; 
    } 
    LNode * GetElem(LinkList L , int index){
        if(index < 1) 
            return NULL;
        LNode *p = L;
        int j = 0 ;
        while(p != NULL && j < index){
            p = p->next;
            j++;
        }
        if(p == NULL)
            return NULL; // 没找到 
        return p;
    }
    LNode * LocateElem(LinkList L , ElemType e){ // 按值查找 
        LNode *p = L->next;
        while(p != NULL && p->data != e){
            p = p->next;
        }
        if(p == NULL)
            return NULL;
        return p;
    }
    int ListLenght(LinkList L){
        int len = 0;
        LNode *p = L->next;
        while(p!=NULL){
            p = p->next;
            len++;
        }
        return len;
    }
    LinkList List_TailInsert(LinkList &L){//尾插法
         // 这是带头节点的
         int x ; // 插入的数据
         LNode *r = L;//r用来返回记录最后一个节点的位置 
         printf("请输入数据(输入999表示结束):");
         scanf("%d",&x);
         LNode *s;
         while(x!= 999){
            s = (LNode*)malloc(sizeof(LNode));
            s->data = x;
            s->next = NULL;
            r->next = s;
            r = s;
            scanf("%d",&x);
         } 
         return L; 
    }
    LinkList List_HeadInsert(LinkList &L){// 头插法 
        LNode *p = L;
        int x ;
        printf("请输入数据(输入888表示结束):");
        scanf("%d" , &x);
        LNode *s ;
        while(x != 888){
            s = (LNode*)malloc(sizeof(LNode));
            s->data = x;
            s->next = p->next;
            p->next = s; // p 节点保持不动 
            scanf("%d",&x); 
        }
        return L;
    }
    LinkList fanzhuanList(LinkList &L){/// 逆置链表 
        LNode *pre = NULL , *r = NULL;
        LNode *head = L ; // 记录一下头节点的地址,我们不对头节点进行操作,防止丢失 
        L = L->next;
        while(L!=NULL){
            r = L->next;
            L->next = pre;
            pre = L;
            L = r;
        }
        /// L == NULL 时 , 链表的最后一个节点是pre ,把head 重新指向它
        head->next = pre; // 把头节点和链表街上 
        return head ;
    }
    LNode* Init() // 初始化头节点 
    {
        LNode *temp ;
        temp = (LNode*)malloc(sizeof(LNode));
        temp->data = -1 ;
        temp->next = NULL;
        return temp;  
    }
    void bianliList(LinkList L)
    {
        LNode *p = L;
        while(p->next!=NULL){ /// 这是带头节点的链表的遍历 
            printf("%d " , p->next->data);
            p = p->next; 
        }
        printf("
    ");
    } 
    int main()
    {
        LinkList L = Init();/// 创建一个链表并初始化它 , 带头节点 
        
        LNode *p = L;
        printf("插入数据:
    ");
        for(int i = 1 ; i <= 5 ; i ++){
            ListInsert(L , i , i); // 插入数据 
        } 
        bianliList(L);
        /// 创建一个临时的节点,在这个节点之后插入一个数据,这个临时的节点指向头节点的下一个节点 
        LNode *temp_Node = p->next ; 
        printf("插入数据(在指定的节点之后):10
    ");
        ListIndexNextInsert(temp_Node , 10); /// 在temp_Node 的后面插入 
        printf("数据插入后:");
        bianliList(L);
        
        // 指定节点前插入数据 , 还是在temp_Node节点前
        printf("插入数据(在指定的节点之前):8
    ");
        ListIndexPriorInsert(temp_Node , 8);
         printf("数据插入后:");
        bianliList(L);
        
        printf("删除指定位置的元素(指定位置为 1):
    ");
        ElemType e;
        ListDelete(L , 1 , e) ; 
        printf("删除的元素:%d
    " , e);
        bianliList(L);
        temp_Node = p->next; // 
        printf("删除指定节点(指定第一个节点):
    ");
        ListDeletePoint(p->next); // temp_Node 就是向第一个节点的
        bianliList(L);
         
        // 返回第 i 个元素 ,返回的是节点
        temp_Node = GetElem(L , 3); // 返回第三个位置的节点 
        printf("第3个位置的元素为:%d
    ", temp_Node->data);
        printf("按值查找(找5):
    ");
        temp_Node = LocateElem(L , 5);
        if(temp_Node != NULL)
            printf("找到5节点
    "); 
        
        temp_Node = L;
        printf("求链表的长度:%d
    " , ListLenght(L));
        
        printf("尾插法测试
    ");
        LinkList temp_tail = Init(); 
        List_TailInsert(temp_tail);
        bianliList(temp_tail);
        
        printf("头插法测试
    ");
        LinkList temp_head = Init(); 
        List_HeadInsert(temp_head);
        bianliList(temp_head);
        
        printf("反转链表测试
    ");
        bianliList(L);
        L = fanzhuanList(L);
        bianliList(L);
        
        
        return 0;
    }

    不带头节点的 

    相关的函数跟上面的一样,内容有点不一样

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    #define ElemType int
    typedef struct LNode{
        ElemType data ; // 我这里用的是Int型的数据
        struct LNode *next; 
    }LNode , *LinkList;// 创建节点
    
    
    bool ListInsert(LinkList &L , int index , ElemType e){/// 不带头节点的 
        if(index < 1 ) 
            return false;
        if(index == 1){ // 不带头节点的要特判1这个位置,因为这是链表是空的 ,不能进行插入操作
            LNode *s = (LNode*)malloc(sizeof(LNode));
            s->data = e ;
            s->next = NULL;
            L = s  ; // 把头节点带回去 
            return true;
        }
        LNode *p = L;    
        int j = 1 ;
        while(p!=NULL && j < index-1){
            p = p->next ;
            j++;
        } 
        // 为插入的数据申请内存 
        LNode *s = (LNode*)malloc(sizeof(LNode));
        s->data = e;
        s->next = p->next ;
        p->next = s;
        return s;
    } 
    bool ListIndexNextInsert(LNode *p , ElemType e){ // 指定节点后插入数据 
        if(p == NULL)
            return false;
        LNode *s;
        s = (LNode*)malloc(sizeof(LNode));
        s->data = e ;
        s->next = p->next;
        p->next = s;
        return true; 
    }
    bool ListIndexPriorInsert(LNode *p , ElemType e){ // 指定节点前插入数据
        // 用交数据的方法
        if(p == NULL)
            return false;
        LNode *s;
        s = (LNode*)malloc(sizeof(LNode));
        s->data = e ;
        s->next = p->next; // 先把节点插入到后面,在交换节点的数据
        p->next = s;
        
        ElemType temp = p->data;
        p->data = s->data;
        s->data = temp;
        return true; 
    }
    bool ListDelete(LinkList &L , int index , ElemType &e){// 删除指定位置的节点,并返回系节点的数据
        if(index < 1 )
            return false;
        LNode *p = L;
        int j = 1 ;
        while(p != NULL && j < index-1){
            p = p->next;
            j++;
        } 
        if(p == NULL)
            return false;
        LNode *q = p->next;
        e = q->data;
        p->next = q->next;
        free(q); 
        return true;
    }
    bool ListDeletePoint(LNode *p){/// 删除指定节点 
        if(p == NULL)
            return false;
        /// 这里注意最后一个节点
        LNode *q = p->next;
        p->data = q->data;
        p->next = q->next;
        free(q); 
        return true;
    }
    LNode *GetElem(LinkList L , int index){/// 查找指定位序的节点
        if(index < 1)
            return NULL;
        LNode *p = L;
        int j = 0;
        while(p!=NULL && j < index-1){
            j++;
            p = p->next;
        } 
        if(p == NULL)
            return NULL;
        return p;
    }
    LNode * LocateElem(LinkList L , ElemType e){ // 按值查找
        LNode *p = L;
        while(p != NULL && p->data != e){
            p = p->next;
        }
        if(p == NULL)
            return NULL;
        return p;
    }
    int ListLenght(LinkList L){/// 求链表长度 
        int len = 0;
        LNode *p = L;
        while(p != NULL){
            len++;
            p = p->next;
        } 
        return len;
    }
    LinkList List_TailInsert(LinkList &L){ // 尾插法插入数据
    // 我们这里是创建链表 , 所以链表L进来都是空的 , 如果不是空链表,用一个while走到最后 
        LNode *r = L;
        int x ;
        printf("请输入数据(输入999表示结束):");
        scanf("%d",&x);
        LNode *s;
        if(r == NULL){ // 传进来的L有可能是空的,这里要特判, 跟带头节点的不一样的点 
            s = (LNode*)malloc(sizeof(LNode));
            s->data = x ;
            s->next = NULL;
            r = s ;
            L = r; // 把第一个节点的位置记住 ,不然就是返回L,L是空的 ,才进这里啊 
            scanf("%d" , &x);
        }
        while(x != 999){
            s = (LNode*)malloc(sizeof(LNode));
            s->data = x ;
            s->next = NULL; // 这里初始化节点的next了,出循环的时候就不用r->next = NULL; 
            r->next = s;
            r = s; 
            scanf("%d" , &x);
        } 
        return L;
        
    }
    LinkList List_HeadInsert(LinkList &L){ // 头插法插入数据
        LNode *p = L;
        LNode *s ;
        int x ;
        printf("请输入数据(输入888表示结束):"); 
        scanf("%d" , &x);
        while(x != 888){
            s = (LNode*)malloc(sizeof(LNode));
            s->data = x ;
            s->next = p ;
            p = s ; // 因为这个是不带头节点的,所以这个p节点要一直向前移动,p节点一直指向最前面 
            scanf("%d" , &x);
        }
        L = p; 
        return L;
    }
    LinkList fanzhuanList(LinkList &L){ // 逆置链表
        LNode *pre = NULL , *r = NULL;
        while(L!=NULL){
            r = L->next;
            L->next = pre;
            pre = L;
            L = r ;
        } 
        L = pre;
        return L;
    }
    void bianliList(LinkList L){
        LNode *p = L;
        while(p != NULL){
            printf("%d " , p->data);
            p = p->next;
        }
        printf("
    ");
    } 
    
    int main()
    {
        LinkList L = NULL; 
        printf("初始化插入数据:");
        for(int i = 1 ; i <= 5 ; i++)
            ListInsert(L , i , i);
        bianliList(L);
        
        LNode *temp_Node = L;
        printf("指定第一个节点后插入数据10:
    ");
        ListIndexNextInsert(temp_Node , 10) ; 
        bianliList(L); 
        
        temp_Node = L;
        //printf("ceshi = %d
    " , temp_Node->data);
        printf("指定第一个节点前插入数据8:
    ");
        ListIndexPriorInsert(temp_Node , 8);
        bianliList(L);
        
        printf("删除指定位序的节点,并返回元素的值(这里指定的是位序3,也就是元素10):
    ");
        ElemType e ;
        ListDelete(L , 3 , e);
        printf("删除的元素:%d
    " , e);
        bianliList(L);
        
        temp_Node = L; // 指向第一个节点
        printf("删除指定的节点(指定第一个节点)
    ");
        ListDeletePoint(temp_Node); // 
        bianliList(L);
        
        printf("查询指定位序的节点(指定3吧)
    ");
        temp_Node = GetElem(L , 3);
        if(temp_Node!=NULL){
            printf("找到位序为3的节点了,节点元素为:%d
    " , temp_Node->data);
        }
        
        printf("查找指定元素值的节(指定5吧)
    ");
        temp_Node = LocateElem(L , 5);
        if(temp_Node!=NULL){
            printf("找到值为5的节点了
    ");
        }
        
        printf("链表的长度为:%d
    " , ListLenght(L));
        
        printf("尾插法插入数据(我们重新创建一个新的链表)
    ");
        LinkList temp_Tail = NULL;
        temp_Tail = List_TailInsert(temp_Tail);
        bianliList(temp_Tail);
        
        printf("头插法插入数据(我们重新创建一个新的链表)
    ");
        LinkList temp_Head = NULL;
        temp_Head = List_HeadInsert(temp_Head);
        bianliList(temp_Head);
        
        printf("
    
    链表逆置
    ");
        printf("逆置前:");
        bianliList(L);
        fanzhuanList(L);
        printf("逆置后:");
        bianliList(L);
        return 0;
    }
  • 相关阅读:
    I/O性能优化
    磁盘性能指标
    磁盘I/O工作原理
    文件系统工作原理
    Linux命令行工具之free命令
    内存性能优化
    内存工作原理
    内存中的Buffer和Cache的区别
    proc文件系统
    oracle 查询 LOB 字段大小
  • 原文地址:https://www.cnblogs.com/Li-ningning/p/14630749.html
Copyright © 2011-2022 走看看