zoukankan      html  css  js  c++  java
  • 数据结构读书笔记第二章 线性表

    2.1 线性表的定义

      线性结构的特点是数据元素之间是一种线性关系,在一个线性表中,数据元素的类型是相同的,或者说线性表是由同一类型的数据元素构成的线性结构.综上所诉:线性表是具有相同数据类型的n(n>=0)个数据元素的有限序列.

    2.2 线性表的顺序存储以及运算实现

    //线性顺序存储的定义
    #define Maxsize 100
    typedef int DataType;
    typedef struct {
            DataType data[Maxsize];
            int last;     //用来记录线性表中最后一个元素在数组中的位置
    }SeqList;
    SeqList L;
    
    //顺序表的初始化
    SeqList *Init_SeqList()
    {
            SeqList *L;
            L=new SeqList;      //分配空间
            if(L)                   //空间分配成功
            {
                    L->last=-1;    
                    return L;
            }
            else                        //申请不成功
                    return -1;
    }
    
    int Insert_SeqList(SeqList L,int i,DataType x)   //插入算法
    {
                int j;
                if(L->last+1>=Maxsize)    //如果超过了预定空间大小
                    return -1;
                if(i<1||i>L->last+2)  //插入的位置是从1到n+1,n==L->last+1
                    return -1;
                for(j=L->last;j>=i-1;j--)
                    L->data[j+1]=L->data[j];
                L->data[i-1]=x;
                L->last++;
                return 1;
    }
    
    int Delete_SeqList(SeqList L,int i)     //删除算法
    {
                if(i<1||i>L->last+1)     //删除的位置从1到n,不存在则返回错误代码
                      return 0;
                for(int j=i;j<=L->last;j++)    //向前移动一位
                    L->data[j-1]=L->data[j];
                L->last--;
                return 1;
    }
    
    int Location_SeqList(SeqList L,DataType x)   //按值查找
    {
                int j=0;
                while(j<=L->last&&L->data[j]!=x)
                    j++;
                if(j>L->last)
                    return -1;
                else 
                    return i;
    }
    

    2.3  顺序表的应用举例

    //将顺序表重新排列成以a1为界的两部分,a1前面的数据元素的值均比a1小,a1后面数据元素的值都比a1大
    void part(SeqList *L)
    {
            int i,j;
            DataType x,y;
            x=L->data[0];
            for(i=1;i<=L->last;i++)
            {
                    if(L->data[i]<x)
                    {
                            y=L->data[i];
                            for(j=i-1;j>=0;j--)    //前面的所有数据都向后移动
                            {
                                    L->data[j+1]=L->data[j];   
                            }
                            L->data[0]=y;
                    }
            }
    }
    
    //有序表的合并算法,A和B是从小到大的升序排列
    void Mymerge(SeqList A,SeqList B,SeqList *C)
    {
                int i,j,k;
                i=j=k=0;
                while(i<=A.last&&j<=B.last)   //依次扫描顺序表A和B中的数据元素
                {
                        if(A.data[i]<B.data[j])
                        {
                                C->data[k]=A.data[i];
                                i++;
                                k++;
                        }
                        else
                        {
                                C->data[k]=B.data[j];
                                j++;
                                k++;
                        }
                  }
                  while(i<=A.last)   //把A中剩下的值赋给C
                  {
                        C->data[k]=A.data[i];
                        i++;
                        k++;
                  }
                  while(j<=B.last)    //把B中剩下的值赋给C
                  {
                        C->data[k]=B.data[j];
                        j++;
                        k++;
                  }
                  C->last=k-1;
    }
        
    //比较线性表大小的算法
    int compare(int A[],int B[],int m,int n)
    {
            int i,j,ms,ns;
            int AS[],BS[];
            i=0;
            while(i<=m&&i<=n&&A[i]==B[i])    
                i++;        //找最大的共同前缀
            ms=ns=0;
            for(j=i;j<n;j++)
            {
                    AS[ms]=A[j];
                    ms++;
            }
            for(j=i;j<n;j++)
            {
                    BS[ms]=B[j];
                    ns++;
            }
            if(ms==ns&&ms==0)
                return 0;     //AS,BS是空表,则A和B是相等
            else
                if(ms==0&&ns>0||ms>0&&ns>0&&AS[0]<BS[0])     //A表小于B表
                        return -1;
                else    
                        return 1;                             //A表大于B表
    }
    

    2.4  线性表的链存储和运算实现

    typedef struct Node    //链表的结构定义
    {
            DataType data;
            struct Node *next;
    }LNode,*LinkList;
    
    //建立链表,第一种从头部插入,头插法
    LinkList *Init_LinkList()
    {
            LinkList L;
            LNode s;
            int x;
            L=NULL;    //首先置为空表
            cin>>x;
            while(x!=Flag)
            {
                s=new LNode;
                s->data=x;
                s->next=L;
                L=s;
                cin>>x;
            }
            return L;
    }
    
    //从尾部插入
    LinkList *Init_LinkList2()
    {
            LinkList  L;
            LNode *r,*s;
            L=r=NULL;
            int x;
            cin>>x;
            while(x!=Flag)
            {
                    s=new LNode;
                    s->data=x;
                    if(L==NULL)      //第一个节点的处理
                            L=s;
                    else
                            r->next=s;    //其他节点的处理
                    r=s;      //r指向新的尾节点
                    cin>>x;
             }
             return L;
    }
    
    //带头节点的求表长
    int length_LinkList1(LinkList L)
    {
            LNode *p;
            int i=0;
            p=L;
            while(p->next)
            {
                    p=p->next;
                    i++;
            }
            return i;   //P指向第i个节点
    }
    
    //不带头节点的单链表求表长
    int length_LinkList2(LinkList L)
    {
            LNode *p;
            int i=0;
            p=L;
            while(p)
            {
                i++;
                p=p->next;
            }
            return i;   //指向第i+1个节点
    }
    
    //按序号查找,带头节点
    int Get_LinkList(LinkList L,int i)
    {
            int j=1;
            LNode *p;
            p=L->next;
            while(p!=NULL&&j<i)
            {
                    p=p->next;
                    j++:
            }
            return p;
    }
    
    //按值查找,带头节点的链表
    int *Location_LinkList(LinkList L,DataType x)
    {
            LNode *p;
            p=L->next;
            while(p!=NULL&&p->data!=x)
                p=p->next;
            return p;
    }
    
    //插入运算,关键在于找到前一个节点
    LinkList Insert_LinkList(LinkList L,int i,DataType x)
    {
            LNode *p,*s;
            p=Get_LinkList(LinkList L,i-1);
            if(p==NULL)    //如果第i-1个节点不存在
                    return 0;
            else
            {
                    s=new LNode;
                    s->data=x;
                    s->next=p->next;
                    p->next=s;
                    return 1;
            }
    }
    
    //删除节点
    LinkList Detele_LinkList(LinkList L,int i)
    {
                LNode *s,*p;
                p=Get_LinkList(L,i-1);
                if(p==NULL)
                    return -1;
                else
                    if(p->next==NULL)
                            return 0;
                    else
                    {
                            s=p->next;     //s指向第i个节点
                            p->next=s->next;   //从链表中删除节点s
                            delete s;               //释放空间
                            return 1;
                    }
    }
    
    
    //将两个单循环链表链接起来,r1,r2是循环链表的尾指针
            p=r1->next;    //保留H1的头指针
            r1->next=r2->next->next;   //头尾相接
            delete r2->next;   //删除H2的头节点
            r2->next=p;   //组成循环链表
    
    //双向链表的定义
    typedef struct DLnode 
    {
                DataType data;
                struct DLnode *prior,*next;
    }DLnode,*DLinkList;
    
    //插入操作,s插到p的节点前面
            s->prior=p->prior;
            p->prior->next=s;
            s->next=p;
            p->prioe=s;
    
    //删除节点
            p->prior->next=p->next;
            p->next->prior=p->prior;
            delete p;

    2.5 链表的应用

    //链表的倒置,采用头插法的原理
    void reverse(LinkList L)
    {
            LNode *p,*s;
            p=L->next;
            L->next=NULL;
            while(p)
            {
                s=p;
                p=p->next;
                s->next=L;       //将当前节点插到头节点后面(注意哲理的"后面"的理解,由于头插的方向)
                L->next=s;
            }
    }
    
    //删除链表中重复节点的算法
    void pur_LinkList(LinkList L)
    {
            LNode *p,*s,*q;
            p=L->next;
            while(p)
            {
                    q=p;
                    while(q->Next)
                    {
                            if(q->next->data==p->data)
                            {
                                    s=q->next;
                                    q->next=s->next;
                                    delete s;
                            }
                            else
                                q=q->next;
                    }
                    p=p->next;
            }
    }
    
    //两个链表的归并算法,A,B是递增有序的,归并成一个递减的有序链表C
    LinkList merge(LinkList A,LinkList B)
    {
            LinkList C;
            LNode *p,*q;
            p=A->next;
            q=B->next;
            C=A;
            C->next=NULL:
            delete B;
            while(p&&q)
            {
                    if(p->data<q->data)
                    {
                            s=p;
                            p=p->next;
                    }
                    else{
                            s=q;
                            q=q->next;
                    }
                    s->next=C->next;    //头插
                    C->next=s;
            }
            if(p==NULL)
                    p=q;
            while(p)      //将剩余的节点一个个摘下,插入倒C表的头部
            {
                    s=p;
                    p=p->next;
                    s->next=C->next;
                    C->next=s;
            }
    }
    

    2.6  算法应用

    1.一个递增有序的线性表,插入一个x,插入到合适的位置,序列还是递增有序

    int InsertSeq(int A[],int num,DataType x)
    {
            int i=num;
            while(i>=0&&A[i]>x)
               {
                    A[i+1]=A[i];   //边找边移动
                    i--;
                }
            A[i+1]=x;
            num++;
            return 1;
    }
    

     2.假设在长度大于1的单循环链表中,既无头节点也无指针,s为指向链表中某个节点的指针,编写删除节点s的直接前驱节点

    void Deletepre(LNode *s)
    {
            LNode *p,*q;
            p=s;
            while(p->next==s)
            {
                    q=p;
                    p=p->next;
            }
            q->next=s;
            delete p;
    }
    

    3.两个单链表A和B分别代表两个集合,其元素递增,编写一个函数求A和B的交际,同样以递增的单链表存储

    LinkList *inter(LinkList A,LinkList B)
    {
            LNode *p,*q,*r,*s;
            LNode *C;
            C=new LNode;
            r=C;
            p=A;
            q=B;
            while(p&&q)
            {
                    if(p->data>q->data)
                        p=p->next;
                    else if(p->data==q->data)
                    {
                            s=new LNode;
                            s->data=p->data;
                            r->next=s;
                            r=s;
                            p=p->next;
                            q=q->next;
                    }
                    else    
                        q=q->next;
            r->next=NULL;
            r=C->next;
            delete C;
            return r;
    }
    

    4. 单链表L是一个递减的有序表,时编写一个高效算法,删除表中值大于min且小于max的节点,同时释放被删除节点的空间

    LinkList delete(LinkList L,int min,int max)
    {
            LNode *p,*q,*s;
            if(L->next)
            {
                    p=L->next;
                    s=L;
                    while(p->data>=max)
                    {
                        s=p;
                        p=p->next;
                    }
                    while(p!=L&&p->data>min)
                        p=p->next;
                    while(s->next!=p)
                    {
                            k=s->next;
                            s->next=k->next;
                            delete k;
                    }
            }
    }
    

    5. 线性表用顺序存储,将前m个元素和后n个元素互换

    void process(SeqList *L,int m,int n)
    {
            int i,k;
            DataType x;
            if(m<=n)
            {
                    for(i=1;i<=m;i++)
                        x=L->data[0];
                        for(k=1;k<=L->last;k++)
                            L->data[k-1]=L->data[k];
                        L->data[L->last]=x;
            }
            else
            {
                    for(i=1;i<=n;i++)
                    x=L->data[L->last];
                    for(k=L->last-1;k>=0;k--)
                        L->data[k+1]=L->data[k];
                    L->data[0]=k;        
            }
    }
    

    6.带头节点的单链表L的节点是按整数值递增的,将x插入,使L有序

    LinkList *insert(LinkList L,int x)
    {
            LNode *p,*s;
            p=L;
            while(p->next&&x>p->next->data)
            {
                    p=p->next;
            }
            s=new LNode;
            s->data=x;
            s->next=p->next;
            p->next=s;
            return L;
    }
    

      

  • 相关阅读:
    sql server中的左连接与右连接的简便写法
    SQL中CONVERT()转化函数的用法 字符串转日期
    Asp.net MVC 中Controller返回值类型ActionResult
    一探前端开发中的JS调试技巧
    String trim 坑 对于ascii码为160的去不掉
    SQL小练习
    Java运行时异常和非运行时异常
    java 子类不能继承父类的static方法
    Java中的类加载器
    搞懂head 和 tail 命令
  • 原文地址:https://www.cnblogs.com/SqLver/p/4909517.html
Copyright © 2011-2022 走看看