数据结构-线性表(二)——单链表

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_39286218/article/details/80249381

任务和代码:

main.cpp
/*  
*All rights reserved  
*文件名称:main.c  
*作者: Osseyda  
完成日期:2018.5.9 
*版本号:v2.  
*  
*问题描述:单链表的应用 
*问题输出:程序的多文件组织形式 
*/    
#include <stdio.h>
#include "list.h"

int main(){
    LinkList *Li, *Li1, *Li2;
    InitList(Li);
    ElemType x[7]= {5,8,7,2,5,4,9};
    ElemType e1, e2;
    /*首插法创建单链表*/
    CreateListH(Li, x, 7);
    printf("首插法创建单链表: ");
    DispList(Li);
    printf("\n");
    /*尾插法创建单链表*/
    CreateListT2(Li, x, 7);
    printf("尾插法创建单链表: ");
    DispList(Li);
    printf("\n");
    /*判断该链表是否为空,不为空则打印长度*/
    if(ListEmpty(Li))
        printf("该链表为空");
    else
        printf("该链表不为空且长为%d",ListLength(Li));
    printf("\n\n");
    /*读指定位置的元素值并打印*/
    if(GetElem(Li,4,e1))
        printf("4号位置对应的元素: %d",e1);
    else
        printf("位置不在链表长度之内");
    printf("\n\n");
    /*读指定元素位置并打印*/
    if(LocateElem(Li,11))
        printf("元素值11对应的位置为: %d",LocateElem(Li,11));
    else
        printf("元素值11对应元素不在此链表内");
    printf("\n\n");
    /*指定位置插入元素并打印新的链表*/
    ListInsert(Li,2,3);
    printf("在第2个元素位置添加元素3:");
    DispList(Li);
    printf("\n");
    /*删除指定位置的元素并打印新的链表*/
    ListDelete(Li,5,e2);
    printf("删除5号位置元素%d后的新链表:",e2);
    DispList(Li);
    printf("\n");
    /*删除元素最大的结点后的新链表*/
    delmaxnode(Li);
    printf("删除元素最大的结点后的新链表:");
    DispList(Li);
    printf("\n");
    /*增序排列结点后的新链表*/
    sortUp(Li);
    printf("增序排列结点后的新链表:");
    DispList(Li);
    printf("\n");
    /*拆分单链表,奇数位和偶数位上的元素各自形成链表*/
    printf("L->L1,L2\n");
    split(Li, Li1, Li2);
    printf("子链表L1: ");
    DispList(Li1);
    printf("子链表L2: ");
    DispList(Li2);
    printf("\n");
    return 0;
}
list.h
#ifndef LIST_H_INCLUDED
#define LIST_H_INCLUDED
typedef char ElemType;
typedef struct LNode{
    ElemType data;
    struct LNode *next;
}LinkList;
void InitList(LinkList *&L);
bool ListEmpty(LinkList *L);
void CreateListH(LinkList *&L, ElemType a[], int n);
void CreateListT1(LinkList *&L, ElemType a[], int n);
void CreateListT2(LinkList *&L, ElemType a[], int n);
void DestoryList(LinkList *&L);
int ListLength(LinkList *L);
void DispList(LinkList *L);
bool GetElem(LinkList *L, int i, ElemType &e);
int LocateElem(LinkList *L, ElemType e);
bool ListInsert(LinkList *&L, int i, ElemType e);
bool ListDelete(LinkList *&L, int i, ElemType &e);
void split(LinkList *&L, LinkList *&L1, LinkList *&L2);
void delmaxnode(LinkList *&L);
void sortUp(LinkList *&L);
#endif // LIST_H_INCLUDED
list.cpp
#include <stdio.h>
#include "list.h"
#include <malloc.h>

//1.初始化线性表
void InitList(LinkList *&L){
    L=(LinkList *)malloc(sizeof(LinkList));
    L->next=NULL;
}

//2.判断线性表是否为空表
bool ListEmpty(LinkList *L){
    return (L->next==NULL);
}

//3.在新结点与首结点间不断插入新结点,
void CreateListH(LinkList *&L, ElemType a[], int n){
    LinkList *s;
    int i;
    L=(LinkList *)malloc(sizeof(LinkList));
    L->next=NULL;
    for(i=0; i<n; i++){
        s=(LinkList *)malloc(sizeof(LinkList));
        s->data=a[i];
        s->next=L->next;
        L->next=s;     //L->next是跟随结点
    }
}

//4.在新插入的结点之后继续插入结点
void CreateListT1(LinkList *&L, ElemType a[], int n){
    LinkList *s, *r; //把r看成结点增量
    int i;
    L=(LinkList *)malloc(sizeof(LinkList));
    r=L;
    for(i=0; i<n; i++){
        s=(LinkList *)malloc(sizeof(LinkList));
        s->data=a[i];
        r->next=s;
        r=s;
    }
    r->next=NULL;
}

//5.在新插入的结点与NULL之间不断插入新结点
void CreateListT2(LinkList *&L, ElemType a[], int n){
    LinkList *s, *r;    //r是跟随结点
    int i;
    L=(LinkList *)malloc(sizeof(LinkList));
    r=L;
    for(i=0; i<n; i++){
        s=(LinkList *)malloc(sizeof(LinkList));
        s->data=a[i];
        s->next=NULL;
        r->next=s;
        r=s;
    }
}

//6.销毁线性链表
void DestoryList(LinkList *&L){
    LinkList *pre=L, *p=L->next;
    while (p!=NULL){
        free(pre);
        pre=p;       //pre是追随结点
        p=p->next;
    }
    free(pre);
}

//7.求线性表的长度
int ListLength(LinkList *L){
    int n=0;
    LinkList *p=L->next;
    while(p!=NULL){
        n++;
        p=p->next;
    }
    return n;
}

//8.输出线性表
void DispList(LinkList *L){
    LinkList *p=L->next;
    while(p!=NULL){
        printf("%d ", p->data);
        p=p->next;
    }
    printf("\n");
}

//9.求线性表指定位置的某个元素
bool GetElem(LinkList *L, int i, ElemType &e){
    LinkList *p=L;
    int j=0;
    while(j<i && p!=NULL){
        j++;
        p=p->next;
    }
    if(p==NULL)
        return false;
    else{
        e=p->data;
        return true;
    }
}

//10.按元素值查找在线性表中的位置
int LocateElem(LinkList *L, ElemType e){
    int i=1;
    LinkList *p=L->next;
    while(p!=NULL && p->data!=e){
        p=p->next;
        i++;
    }
    if(p==NULL)
        return 0;
    else
        return i;
}

//11.插入数据元素
bool ListInsert(LinkList *&L, int i, ElemType e){
    LinkList *q=L, *s;
    int j=0;
    while(j<i-1 && q!=NULL){
        j++;
        q=q->next;
    }
    if(j==i-1){
        if(q==NULL)
            return false;
        else{
            s=(LinkList *)malloc(sizeof(LinkList));
            s->data=e;
            s->next=q->next;
            q->next=s;
        }
        return true;
    }
    else
        return false;
}

//12.删除数据元素
bool ListDelete(LinkList *&L, int i, ElemType &e){
    LinkList *q=L, *p=L->next;
    int j=1;
    while(j<i && p!=NULL){
        j++;
        q=p;
        p=p->next;
    }
    if(i==j){
        if(p==NULL)
            return false;
        else{
            e=p->data;
            q->next=p->next;
            free(p);
            return true;
        }
    }
    else
        return false;
}

//13.拆分单链表
void split(LinkList *&L, LinkList *&L1, LinkList *&L2){
    LinkList *p=L->next, *q, *r1;
    L1=L;
    r1=L1;
    L2=(LinkList *)malloc(sizeof(LinkList));
    L2->next=NULL;
    while(p!=NULL){
        r1->next=p;
        r1=p;             //r1是p的跟随结点
        p=p->next;
        if(p!=NULL){   //防止出现奇数个元素时,q出现野指针的情况
            q=p->next;
            p->next=L2->next;
            L2->next=p;
            p=q;              //q是p的领跑结点
        }
    }
    r1->next=NULL;
}

//14.删除最大元素节点
void delmaxnode(LinkList *&L){
    LinkList *p=L->next, *pre=L, *maxp=p, *maxpre=pre;
    while(p!=NULL){
        if(maxp->data < p->data){
            maxp=p;
            maxpre=pre;  //pre的作用
        }
        pre=p;
        p=p->next;   //pre是p的跟随结点
    }
    maxpre->next=maxp->next;
    free(maxp);
}

//15.增序排列结点
void sortUp(LinkList *&L){
    LinkList *p, *pre, *q;   //pre是p的前一个结点
    p=L->next->next;
    L->next->next=NULL;
    while(p!=NULL){
        q=p->next;           //在p->next未变化之前先定下p的领跑结点
        pre=L;
        while(pre->next!=NULL && pre->next->data<p->data)
            pre=pre->next;   //找到pre
        p->next=pre->next;
        pre->next=p;
        p=q;                 //若p=p->next则进入死循环
    }
}


问题与解决:

1:void soetUp():使一个带头结点的单链表里的元素递增有序排列
我的疑问:在外循环p!=NULL条件下,内循环pre->next!=NULL是不是多余呢?
因为从程序上看,pre永远是p的前一个结点
问题的解决:(应从理解算法思想开始)看到循环以上的定义p=L->next->next;L->next->next=NULL;

即p是一个结点变量,举个例子,如图,


该链表只有两个元素,当pre->data=3,

pre->next为空,pre->next->data是无法获得的,而之前我误认为pre->next即p,
pre->next->data=p->data跳出循环,这显然错误。故内循环中pre->next==NULL时应退出

PS: 很显然,并没有从程序中理解算法的思想


猜你喜欢

转载自blog.csdn.net/sinat_39286218/article/details/80249381