首页 > 其他 > 详细

王道数据结构代码:单链表的操作

时间:2021-04-08 23:46:50      阅读:28      评论:0      收藏:0      [点我收藏+]

带头节点的

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("\n");
} 
int main()
{
    LinkList L = Init();/// 创建一个链表并初始化它 , 带头节点 
    
    LNode *p = L;
    printf("插入数据:\n");
    for(int i = 1 ; i <= 5 ; i ++){
        ListInsert(L , i , i); // 插入数据 
    } 
    bianliList(L);
    /// 创建一个临时的节点,在这个节点之后插入一个数据,这个临时的节点指向头节点的下一个节点 
    LNode *temp_Node = p->next ; 
    printf("插入数据(在指定的节点之后):10\n");
    ListIndexNextInsert(temp_Node , 10); /// 在temp_Node 的后面插入 
    printf("数据插入后:");
    bianliList(L);
    
    // 指定节点前插入数据 , 还是在temp_Node节点前
    printf("插入数据(在指定的节点之前):8\n");
    ListIndexPriorInsert(temp_Node , 8);
     printf("数据插入后:");
    bianliList(L);
    
    printf("删除指定位置的元素(指定位置为 1):\n");
    ElemType e;
    ListDelete(L , 1 , e) ; 
    printf("删除的元素:%d\n" , e);
    bianliList(L);
    temp_Node = p->next; // 
    printf("删除指定节点(指定第一个节点):\n");
    ListDeletePoint(p->next); // temp_Node 就是向第一个节点的
    bianliList(L);
     
    // 返回第 i 个元素 ,返回的是节点
    temp_Node = GetElem(L , 3); // 返回第三个位置的节点 
    printf("第3个位置的元素为:%d\n", temp_Node->data);
    printf("按值查找(找5):\n");
    temp_Node = LocateElem(L , 5);
    if(temp_Node != NULL)
        printf("找到5节点\n"); 
    
    temp_Node = L;
    printf("求链表的长度:%d\n" , ListLenght(L));
    
    printf("尾插法测试\n");
    LinkList temp_tail = Init(); 
    List_TailInsert(temp_tail);
    bianliList(temp_tail);
    
    printf("头插法测试\n");
    LinkList temp_head = Init(); 
    List_HeadInsert(temp_head);
    bianliList(temp_head);
    
    printf("反转链表测试\n");
    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("\n");
} 

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:\n");
    ListIndexNextInsert(temp_Node , 10) ; 
    bianliList(L); 
    
    temp_Node = L;
    //printf("ceshi = %d\n" , temp_Node->data);
    printf("指定第一个节点前插入数据8:\n");
    ListIndexPriorInsert(temp_Node , 8);
    bianliList(L);
    
    printf("删除指定位序的节点,并返回元素的值(这里指定的是位序3,也就是元素10):\n");
    ElemType e ;
    ListDelete(L , 3 , e);
    printf("删除的元素:%d\n" , e);
    bianliList(L);
    
    temp_Node = L; // 指向第一个节点
    printf("删除指定的节点(指定第一个节点)\n");
    ListDeletePoint(temp_Node); // 
    bianliList(L);
    
    printf("查询指定位序的节点(指定3吧)\n");
    temp_Node = GetElem(L , 3);
    if(temp_Node!=NULL){
        printf("找到位序为3的节点了,节点元素为:%d\n" , temp_Node->data);
    }
    
    printf("查找指定元素值的节(指定5吧)\n");
    temp_Node = LocateElem(L , 5);
    if(temp_Node!=NULL){
        printf("找到值为5的节点了\n");
    }
    
    printf("链表的长度为:%d\n" , ListLenght(L));
    
    printf("尾插法插入数据(我们重新创建一个新的链表)\n");
    LinkList temp_Tail = NULL;
    temp_Tail = List_TailInsert(temp_Tail);
    bianliList(temp_Tail);
    
    printf("头插法插入数据(我们重新创建一个新的链表)\n");
    LinkList temp_Head = NULL;
    temp_Head = List_HeadInsert(temp_Head);
    bianliList(temp_Head);
    
    printf("\n\n链表逆置\n");
    printf("逆置前:");
    bianliList(L);
    fanzhuanList(L);
    printf("逆置后:");
    bianliList(L);
    return 0;
}

 

王道数据结构代码:单链表的操作

原文:https://www.cnblogs.com/Li-ningning/p/14630749.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!