zoukankan      html  css  js  c++  java
  • 从新定义线性链表及其基本操作

      链表在空间的合理利用上和插入、删除时不需要移动等优点,因此在很多场合下,它是线性表的首先储存结构。然而它也存在着实现某些基本操作,如求线性表的长度时不如顺序储存结构的特点。因而从新定义线性链表及其基本操作

    头文件:

    #define TRUE 1
    #define FALSE 0
    #define OK 1
    #define ERROR 0
    #define INFEASIBLE -1
    #define MYOVERFLOW -2
    typedef int Status;
    typedef int Elemtype;
    typedef struct LNode{//结点类型
        Elemtype data;
        LNode *next;
    }*Link,*Position;
    typedef struct{//链表类型
        Link head, tail;//分别指向线性链表中的头结点和最后一个结点
        int len;//指示线性链表中数据元素的个数
    }LinkList;
    Status compare(Elemtype s1, Elemtype s2);//比较两者的大小,相等返回TRUE,否则返回FALSE
    Status visit(LinkList L);//若存在,则遍历L返回OK,否则返回ERROR
    Status Create_List(LinkList &);//创造一个链表
    Status MakeNode(Link &p, Elemtype e);
    //分配由p指向的值为e的结点,并返回OK;若分配失败,则返回ERROR
    void FreeNode(Link &p);
    //释放p所指结点
    Status InitList(LinkList &L);
    //构造一个空的线性链表L
    Status DestroyList(LinkList &L);
    //销毁线性链表L,L不再存在
    Status ClearList(LinkList &L);
    //将线性链表L重置为空表,并释放原链表的结点空间
    Status InsFirst(Link h, Link s);
    //已知h指向线性链表的头结点,将s所指结点插入在第一个结点之前
    Status DelFirst(Link h, Link &q);
    //已知h指向线性链表的头结点,删除链表中的第一个结点并以q返回
    Status Append(LinkList &L, Link s);
    //将指针s所指(彼此以指针相链)的一串结点链接在线性链表L的最后一个结点
    //之后,并改变链表L的尾指针指向新的尾结点
    Status Remove(LinkList &L, Link &q);
    //删除线性链表L中的尾结点并以q返回,改变链表L的尾指针指向新的尾结点
    Status InsBefore(LinkList &L, Link &p, Link s);
    //已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之前,
    //并修改指针p指向新插入的结点
    Status InsAfter(LinkList &L, Link &p, Link s);
    //已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之后,
    //并修改指针p指向新插入的结点
    Status SetCurElem(Link &p, Elemtype e);
    //已知p指向线性链表中的一个结点,用e更新p所指结点中数据元素的值
    Elemtype GetCurElem(Link p);
    //已知p指向线性链表中的一个结点,返回p所指结点中数据元素的值
    Status ListEmpty(LinkList L);
    //若线性链表L为空表,则返回TRUE,否则返回FALSE
    int ListLength(LinkList L);
    //返回线性链表L中元素个数
    Position GetHead(LinkList L);
    //返回线性链表L中头结点的位置
    Position GetLast(LinkList L);
    //返回线性链表L中最后一个结点的位置
    Position PriorPos(LinkList L, Link p);
    //已知p指向线性链表L中的一个结点,返回p所指结点的直接前驱的位置,
    //若无前驱,则返回NULL
    Position NextPos(LinkList L, Link p);
    //已知p指向线性链表L中的一个结点,返回p所指结点的直接后继的位置,
    //若无后继,则返回NULL
    Status LocatePos(LinkList L,int i, Link &p);
    //返回p指示线性链表L中第i个结点的位置并返回OK,i值不合法时返回ERROR
    Position LocateElem(LinkList L, Elemtype e, Status(*P)(Elemtype, Elemtype));
    //返回线性链表L中第一个与e满足函数p()判定关系的元素的位置,
    //若不存在这样的元素,则返回NULL
    Status ListTraverse(LinkList L, Status(*visit)(LinkList));
    //依次对L的每个元素调用函数visit()。一旦visit()失败,则操作失败

    上述操作的实现:

    Status MakeNode(Link &p, Elemtype e)
    //分配由p指向的值为e的结点,并返回OK;若分配失败,则返回ERROR
    {
        p = new LNode;//为*p分配空间
        if (p){
            p->data = e;
            return OK;
        }
        else
            return ERROR;
    }
    void FreeNode(Link &p)
    //释放p所指结点
    {
        delete p;//删除*p所占用的空间
    }
    Status InitList(LinkList &L)
    //构造一个空的线性链表L
    {
        Link p = new LNode;
        if (p){
            L.head = p;//新建一个结点,并且头指针和尾指针都指向该结点,长度为0
            L.tail = L.head;
            L.len = 0;
            return OK;
        }
        else
            return ERROR;
        
    }
    Status Create_List(LinkList &L)//创造一个链表
    {
        if (InitList(L)){//初始化链表
            cout << "please input the length of the linklist:" << endl;
            int len;
            cin >> len;
            L.len = len;
            cout << "please input the data of the linklist:" << endl;
            for (int i = 1; i <= len; i++){
                Link temp = new LNode;//创建结点
                cin >> temp->data;//输入结点的数据元素
                L.tail->next = temp;//将结点插入到表的末尾
                L.tail = L.tail->next;
                }
            L.tail->next = NULL;
            return OK;
        }
        else return ERROR;
    }
    Status visit(LinkList L)//若存在,则遍历L返回OK,否则返回ERROR
    {
        if (L.head){
            cout << "the data of the list is:" << endl;
            L.head = L.head->next;
            for (; L.head != L.tail;){
                cout << L.head->data << " ";
                L.head = L.head->next;
            }
            cout << L.tail->data << endl;//最后输出尾结点的数据元素
            return OK;
        }
        else return ERROR;
    }
    Status ListTraverse(LinkList L, Status(*visit)(LinkList))
    //依次对L的每个元素调用函数visit()。一旦visit()失败,则操作失败
    {
        if (visit(L)){
            
            return OK;}
        else
        {
            return ERROR;
        }
    }
    Status DestroyList(LinkList &L)
    //销毁线性链表L,L不再存在
    {
        
        for (; L.head != L.tail; L.len--){//释放链表中结点所占的内存空间
            Link pt;
            pt = L.head;
            L.head = L.head->next;
            delete pt;
    
        }
        delete L.head;
        if (L.len == 0){//使L的头指针和尾指针不指向任何地方
            L.head = NULL;
            L.tail = NULL;
            LinkList *p = &L;
            delete p;
            return OK;
        }
        else
        {
            return ERROR;
        }
    }
    Status ClearList(LinkList &L)
    //将线性链表L重置为空表,并释放原链表的结点空间
    {
        Link temp = L.head;
        L.head = L.head->next;
        for (; L.len>0; L.len--){//释放链表中的结点所占的内存空间
            Link pt;
            pt = L.head;
            L.head = L.head->next;
            delete pt;
        }
        L.head = temp;
        if (L.len == 0&&L.head==L.tail){
            return OK;
        }
        else
        {
            return ERROR;
        }
    }
    Status InsFirst(Link h, Link s)
    //已知h指向线性链表的头结点,将s所指结点插入在第一个结点之前
    {
        if (h){//判断头结点是否存在
            s->next = h->next;//将s结点插入到表中
            h->next = s;
            return OK;
        }
        else return ERROR;
    }
    Status DelFirst(Link h, Link &q)
    //已知h指向线性链表的头结点,删除链表中的第一个结点并以q返回
    {
        if (h->next){//判断第一个结点是否存在
            q = h->next;//给q赋予第一个结点的值
            h->next = h->next->next;//将第一个结点从链表中删除
            q->next = NULL;
            return OK;
        }
        else return ERROR;
    }
    Status Append(LinkList &L, Link s)
    //将指针s所指(彼此以指针相链)的一串结点链接在线性链表L的最后一个结点
    //之后,并改变链表L的尾指针指向新的尾结点
    {
        if (s){
            Link temp = s;
            for (; s->next; s = s->next)
            {
                L.len++;
            }//让S移动到链表的最后一个结点
            L.len++;
            L.tail->next = temp;
            L.tail = s;//使L.tail指向最后一个结点
            return OK;
        }
        else return ERROR;
    }
    Status Remove(LinkList &L, Link &q)
    //删除线性链表L中的尾结点并以q返回,改变链表L的尾指针指向新的尾结点
    {
        if (L.head != L.tail){
            q = L.tail;//用q返回尾结点
            Link temp;
            temp = L.head;
            for (; temp->next != L.tail; temp = temp->next){}//使temp指向尾结点的前一个结点
            L.tail = temp;//使尾结点指向新的尾结点
            L.tail->next = NULL;
            delete temp->next;//删除旧的尾结点
            L.len--;
            return OK;
        }
        else return ERROR;
    }
    Status InsBefore(LinkList &L, Link &p, Link s)
    //已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之前,
    //并修改指针p指向新插入的结点
    {
        Link temp=L.head;
        for (; temp->next != p&&temp; temp = temp->next){}
        if (temp->next == p){
            s->next = p;
            temp->next = s;
            p = s;
            L.len++;
            return OK;
        }
        else return ERROR;
    }
    Status InsAfter(LinkList &L, Link &p, Link s)
    //已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之后,
    //并修改指针p指向新插入的结点
    {
        Link temp = L.head;
        for (; temp != p&&temp; temp = temp->next){}
        if (temp == p){
            temp->next=s;
            s->next = p;
            p = s;
            if (temp == L.tail)
                L.tail = s;
            L.len++;
            return OK;
        }
        else return ERROR;
    }
    Status SetCurElem(Link &p, Elemtype e)
    //已知p指向线性链表中的一个结点,用e更新p所指结点中数据元素的值
    {
        if (p){
            p->data = e;
            return OK;
        }
        else return ERROR;
    }
    Elemtype GetCurElem(Link p)
    //已知p指向线性链表中的一个结点,返回p所指结点中数据元素的值
    {
        if (p){
            return p->data;
        }
        else return NULL;
    }
    Status ListEmpty(LinkList L)
    //若线性链表L为空表,则返回TRUE,否则返回FALSE
    {
        if (L.len == 0){
            return TRUE;
        }
        else return FALSE;
    }
    int ListLength(LinkList L)
    //返回线性链表L中元素个数
    {
        return L.len;
    }
    Position GetHead(LinkList L)
    //返回线性链表L中头结点的位置
    {
        return L.head;
    }
    Position GetLast(LinkList L)
    //返回线性链表L中最后一个结点的位置
    {
        return L.tail;
    }
    Position PriorPos(LinkList L, Link p)
    //已知p指向线性链表L中的一个结点,返回p所指结点的直接前驱的位置,
    //若无前驱,则返回NULL
    {
        Link temp = L.head;
        for (; temp->next != p&&temp; temp = temp->next){}
        if (temp->next == p){
            return temp;
        }
        else return NULL;
    }
    Position NextPos(LinkList L, Link p)
    //已知p指向线性链表L中的一个结点,返回p所指结点的直接后继的位置,
    //若无后继,则返回NULL
    {
        Link temp = L.head->next;
        for (; temp != p->next&&temp; temp = temp->next){}
        if (temp == p->next){
            return temp;
        }
        else return NULL;
    }
    Status LocatePos(LinkList L, int i, Link &p)
    //返回p指示线性链表L中第i个结点的位置并返回OK,i值不合法时返回ERROR
    {
        for (int j = 1; L.head&&j <= i; j++, L.head = L.head->next){}
        if (L.head){
            p = L.head;
            return OK;
        }
        else return ERROR;
    }
    Status compare(Elemtype s1, Elemtype s2){
        if (s1 == s2)return OK;
        else return ERROR;
    }
    Position LocateElem(LinkList L, Elemtype e, Status(*P)(Elemtype s1, Elemtype s2))
    //返回线性链表L中第一个与e满足函数p()判定关系的元素的位置,
    //若不存在这样的元素,则返回NULL
    {
        for (; !P(L.head->next->data, e) && L.head->next; L.head = L.head->next){}
        if (!L.head->next){
            return L.head->next;
        }
        else return NULL;
    }

    用这些基本操作实现插入操作和将两个非递减排列合并成一个新的非递减序列
    头文件:

    Status ListInsert_L(LinkList &L, int i, Elemtype e);
    //在带头结点的单链线性表L的第i个元素之前插入元素e
    Status MergeList_L(LinkList &La, LinkList &Lb, LinkList &Lc, int(*compare)(Elemtype, Elemtype));
    //已知单链线性表La和Lb的元素按值非递减排列。
    //归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列
    int compare1(Elemtype a, Elemtype b);//返回a-b的值

    操作的实现:

    Status ListInsert_L(LinkList &L, int i, Elemtype e)
    //在带头结点的单链线性表L的第i个元素之前插入元素e
    { 
        Link h,s;    
        if (!MakeNode(s, e))return ERROR;
        if (i = L.len + 1){
            s->next = L.tail->next;
            L.tail->next = s;
            L.tail = L.tail->next;
        }
        else {
            if (!LocatePos(L, i - 1, h))return ERROR;
            InsFirst(h, s);    
        }
        L.len++;
        return OK;
    }
    int compare1(Elemtype a, Elemtype b){
        return a - b;
    }
    Status MergeList_L(LinkList &La, LinkList &Lb, LinkList &Lc, int(*compare)(Elemtype, Elemtype))
    //已知单链线性表La和Lb的元素按值非递减排列。
    //归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列
    {
        if (!InitList(Lc))return ERROR;
        Link ha; Link hb;
        ha = GetHead(La); hb = GetHead(Lb);
        Link pa; Link pb;
        pa = NextPos(La, ha);
        pb = NextPos(Lb, hb);
        int lenLc = La.len + Lb.len;
        while (pa&&pb){
            Link q;
            Elemtype a, b;
            a = GetCurElem(pa); b = GetCurElem(pb); 
            if (compare(a, b)<=0){
                DelFirst(ha, q);
                Append(Lc, q);
                pa = NextPos(La, ha);    
            }
            else{
                DelFirst(hb, q);
                Append(Lc, q);
                pb = NextPos(Lb, hb);
            }
        }   
            if (pa)Append(Lc, pa);
            else Append(Lc, pb); 
            FreeNode(ha); FreeNode(hb);
            Lc.len = lenLc;
    
        return OK;
    }

    主函数:

    int _tmain(int argc, _TCHAR* argv[])
    {
        LinkList l1,l2,l3;
        Create_List(l1);
        Create_List(l2);
        MergeList_L(l1, l2, l3,compare1);
        ListTraverse(l3, visit);
        return 0;
    
    }

    最终得到的结果如下图:

  • 相关阅读:
    sencha touch 扩展篇之将sencha touch打包成安装程序(上)- 使用sencha cmd打包安装程序
    sencha touch 扩展篇之使用sass自定义主题样式 (下)通过css修改官方组件样式以及自定义图标
    一个不错的android组件的网站
    sencha touch 扩展篇之使用sass自定义主题样式 (上)使用官方的api修改主题样式
    sencha touch 入门系列 (九) sencha touch 布局layout
    面试题总结
    国外接活网站Elance, Freelancer和ScriptLance的介绍和对比
    sencha touch 入门系列 扩展篇之sencha touch 项目打包压缩
    Android Design Support Library——Navigation View
    设计模式——命令模式
  • 原文地址:https://www.cnblogs.com/csudanli/p/4802163.html
Copyright © 2011-2022 走看看