LinearList

来源:互联网 发布:free mobile java 编辑:程序博客网 时间:2024/06/11 04:16
1、线性表的定义

    线性表是具有相同特性数据元素的一个有限序列。该序列中所含元素的个数叫做线性表的长度,用n(n>0)表示。n可以为0,表示该线性表是一个空表。

2、线性表的逻辑特性

    只有一个表头元素,只有一个表尾元素,表头元素没有前驱,表尾元素没有后继,除表头和表位元素之外,其他元素只有一个直接前驱,也只有一个直接后继。

3、结构体定义

#define maxSize 100 //这里定义一个整型常量maxSize,值为100//1、顺序表的结构体定义typedef struct{    int data[maxSize];  //存放顺序元素的数组(默认是int型,可根据题目要求将int转换成其他的数据类型)    int length; //存放顺序表的长度}Sqlist;    //顺序表类型的定义//2、单链表结点定义typedef struct LNode{    int data;   //data中存放结点数据域(默认是int型)    struct LNode *next; //指向后继结点的指针}LNode; //定义单链表结点类型//3、双链表结点定义typedef struct DLNode{    int data;   //data中存放结点数据域(默认是int型)    struct DLNode *prior;   //指向前驱结点的指针    struct DLNode *next;    //指向后继结点的指针}DLNode;    //定义双链表结点类型

4、顺序表的操作

//返回第一个比x大的元素的位置int findElem(Sqlist L, int x){    int i;    for (i=0; i<L.length; ++i)    {        if (x < L.data[i])  //对顺序表中的元素从小到大逐个进行判断,看x是否小于当前所扫描到的元素,如果小于则返回当前位置i        {            return i;        }    }    return i;   //如果顺序表中不存在比x大的元素,则应将x插入表尾元素,返回i来标记这种情况(i<L.length这一句不成立,而退出for循环后,i正好指示了表尾元素之后的位置,同样也是正确的插入位置)}//移动元素、并插入新的元素void insertElem(Sqlist &L, int x)   //L本身要发生变化,因此要使用引用型{    int p,i;    p = findElem(L,x);  //调用函数findElem()来找到插入位置p    for (i=L.length-1; i>=p; --i)    {        L.data[i+1] = L.data[i];    //从右向左,逐个将元素右移一个位置    }    L.data[p] = x;  //将x放在插入位置p上    ++(L.length);   //表内元素多了1个,因此表长自增1}//在顺序表中查找第一个值为e的元素算法int findElem(Sqlist L, int e){    int i;    for (i=0; i<L.length; ++i)    {        if (e == L.data[i])        {            return i;   //若找到,则返回下标        }    }    return -1;  //没找到,返回-1,作为失败标记}//在第P个位置插入元素eint insertElem(Sqlist &L, int p, int e) //L本身要发生改变,所以要有引用型{    int i;    if (p<0 || p>L.length || L.length==maxSize) //位置错误或者表长已经达到顺序表的最大允许值,此时插入不成功,返回0    {        return 0;    }    for (i=L.length-1; i>=p; --i)    {        L.data[i+1] = L.data[i];    //从后往前,逐个将元素往后移动一个位置    }    L.data[p] = e;  //将e放在插入位置P上    ++(L.length);   //表内元素多了1个,长度自增1    return 1;   //插入成功,返回1}//删除顺序表L中下标为p(0<=p<=length-1)的元素,成功返回1,否则返回0,并将被删除元素的值赋给e。int deleteElem(Sqlist &L, int p, int &e){    int i;    if (p<0 || p>L.length-1)    {        return 0;   //位置不对返回0,代表删除不成功    }    e = L.data[p];  //将被删除元素的值赋给e    for (i=p; i<L.length-1; ++i)    //从p位置开始,将其后边的元素逐个前移一个位置    {        L.data[i] = L.data[i+1];    }    --(L.length);   //表长减1    return 1;   //删除成功,返回1}//初始化顺序表的算法//只需将length设置为0,如下:void initList(Sqlist &L)    //L本身要发生改变,所以用引用型{    L.length = 0;}//求指定位置元素的算法//用e返回L中p(0<=p<=length-1)位置上的元素,如下:int getElem(Sqlist L, int p, int &e)    //要改变,所以用引用型{    if (p<0 || p>L.length-1)    //p值越界错误,返回0    {        return 0;    }    e = L.data[p];    return 1;}

5、单链表的操作

//将两个递增的单链表归并成一个递增的单链表void merge(LNode *A, LNode *B, LNode *&C){    LNode *p = A->next; //p来跟踪A的最小值结点    LNode *q = B->next; //q来跟踪B的最小值结点    LNode *r;   //r始终指向C的终端节点    C = A;  //用A的头结点来做C的头结点    C->next = NULL;    free(B);    //B的头结点已经没用,因而释放掉    r = C;  //r指向C,因为此时头结点也是终端节点    while (p != NULL && q != NULL)  //当p和q都不为空时,选取p与q所指结点中较小者插入C的尾部    {        /**        以下的if else语句中,r始终指向当前链表的终端结点,作为接纳新结点的一个媒介,通过它,新结点被链接入C并且重新指向新的终端结点,以便于接收下一个新结点,这里体现了建立链表的尾插法的思想        */        if (p->data <= q->data)        {            r-next = p;            p = p->next;            r = r->next;        }        else        {            r->next = q;            q = q->next;            r = r->next;        }    }    r->next = NULL; //此句可去掉    if (p != NULL)  //将p及p之后链接到C的尾部    {        r->next = p;    }    if (q != NULL)  //将q及q之后链接到C的尾部    {        r->next = q;    }}//尾插法建立单链表void createlistR(LNode *&C, int a[], int n) //要改变的变量用引用型{    LNode *s,*r;    //s用来指向新申请的结点,r始终指向C的终端结点    int i;    C = (LNode*)malloc(sizeof(LNode));  //申请C的头结点空间    C->next = NULL;    r = C;  //r指向头结点,因为此时头结点就是终端结点    for (i=0; i<n; ++i) //循环申请n个结点来接收数组a中的元素    {        s = (LNode*)malloc(sizeof(LNode));  //s指向新申请的结点        s->data = a[i]; //用新申请的结点来接收a中的一个元素        r->next = s;    //用r来接收新结点        r = r->next;    //r指向终端结点,以便于接纳下一个到来的结点    }    r->next = NULL; //数组a中所有的元素都已经装入链表C中,C的终端结点的指针域置为NULL,C建立完成}//头插法建立单链表void createlistF(LNode *&C, int a[], int n){    LNode *s;    int i;    C = (LNode*)malloc(sizeof(LNode));    C->next = NULL;    for (i=0; i<n; ++i)    {        s = (LNode*)malloc(sizeof(LNode));        s->data = a[i];        //头插法的关键        s->next = C->next;  //s所指新结点的指针域next指向C中的开始结点        C->next = s;    //头结点的指针域next指向s结点,使得s成为新的开始结点    }}//利用头插法将两个递增的单链表归并成一个递减的单链表void merge(LNode *A, LNode *B, LNode *&C){    LNode *p = A->next;    LNode *q = B->next;    LNode *s;    C = A;    C->next = NULL;    free(B);    while (p != NULL && q != NULL)    {        if (p->data <= q->data)        {            s = p;            p = p->next;            s->next = C->next;            C->next = s;        }        else        {            s = q;            q = q->next;            s->next = C->next;            C->next = s;        }    }    /**    下边这两个循环是和求递增归并序列不同的地方,必须将剩余元素逐个插入C的头部才能得到最终的递减序列    */    while (p != NULL)    {        s = p;        p = p->next;        s->next = C->next;        C->next = s;    }    while (q != NULL)    {        s = q;        q = q->next;        s->next = C->next;        C->next = s;    }}//查找链表C(带头结点)中是否存在一个值为x的结点,若存在,则删除该结点并返回1,否则返回0int findAndDelete(LNode *C, int x){    LNode *p, *q;    p = C;    //查找部分开始    while (p->next != NULL)    {        if (p->next->data == x)        {            break;        }        p = p->next;    }    //查找部分结束    if (p->next == NULL)    {        return 0;    }    else     {        //删除部分开始        q = p->next;        p->next = p->next->next;        free(q);        //删除部分结束        return 1;    }}

6、双链表的操作

//尾插法建立双链表void createDlistR(DLNode *&L, int a[], int n){    DLNode *s, *r;    int i;    L = (DLNode*)malloc(sizeof(DLNode));    L->prior = NULL;    L->next = NULL;    r = L;  //r始终指向终端结点,开始头结点也是尾结点    for (i=0; i<n; ++i)    {        s = (DLNode*)malloc(sizeof(DLNode));        s->data = a[i];        /**        下边3句将s插入到L的尾部,并且r指向s,s->prior = r;这一句是和建立单链表不同的地方        */        r->next = s;        s->prior = r;        r = s;    }    r->next = NULL;}//在双链表中查找元素x,并返回结点指针DLNode* findNode(DLNode *C, int x){    DLNode *p = C->next;    while (p != NULL)    {        if (p->data == x)        {            break;        }        p = p->next;    }    return p;   //如果找到,则p中内容是结点地址(循环因break结束);如果没找到,则p中内容是NULL(循环因p等于NULL而结束)。}//插入结点的算法//假设在双链表中p所指的结点之后插入一个结点s,其操作语句如下:s->next = p->next;s->next = p;p->next = s;s->next->prior = s; //假如p指向最后一个结点,则本行可去掉//删除结点的算法//设要删除双链表中p结点的后继结点,其操作语句如下:q = p->next;p->next = q->next;q->next->prior = p;free(q);


原创粉丝点击