1. 程式人生 > >數據結構基礎(一)

數據結構基礎(一)

數據結構

線性表

線性順序表

1、線性表的數據操作

技術分享圖片

2、使用定義的函數實現兩個集合LA和LB的合並:

void unionList(List LA,List LB,List &LC)
{
    int lena,i;
    ElemType e;
    InitList(LC);
    //將LA的所有元素插入到LC中
    for (i=1;i<=ListLength(LA);i++)
    {
        GetElem(LA,i,e);
        ListInsert(LC,i,e);
     } 
     lena=ListLength(LA);

     //將LB的所有元素插入到LC
     for(i=1;i<ListLength(LB);i++)
     {
         GetElem(LB,i,e);
         if (!LocateElem(LA,e))
             ListInsert(LC,++lena,e);
      } 
 } 

3、順序表存儲類型的定義

# define MaxSize 50
typedef struct
{

    ElemType date[MaxSize];
        int length;
}SqList;

4、創建線性表

void CreateList(Sqlist *&L,ElemType a[],int n)
{
    int i;
    L=(SqList *)malloc(sizeof(SqList)); 
    // malloc 相當於new,分配SqList大小的內存空間,指向SqLost的指針,並將地址賦值給L 

    for (i=0;i<n;i++)
        L->data[i]=a[i];
    L->length=n;    
}

5、初始化線性表

void InitList(SqList *&L) // 應用指針
{
    L=(SqList *)malloc(sizeof(SqList));
    L->length=0;   // 初始化線性表的長度 
} 

6、銷毀線性表

void DestroyList(SqlList *&L)
{

 free(L); 
}

7、判斷線性表是否為空

bool ListEmpty(SqList *L)
{
    return(L->length==0);
}

8、求線性表的長度

int ListLength(SqList *L)
{
    return(L->length);  
}

9、輸出線性表

void DispList(SqList *L)
{
    int i;
    if (ListEmpty(L))
        return;
    for (i=0;i<L->length;i++)
        printf("%d ",L->data[i]);
    printf("\n");
}

10、求某個數據元素的值,返回L中的第i個元素的值,並存入e中,1<=i<=ListLength(L)

bool GetElem(SqList *L,int i,ElemType &e)
{
    if (i<1||i>L->length)
        return false;
    e=L->data[i-1];
    return true;
}

11、按元素值查找

int LocateElem(L,e)
{
    int i = 0;
    while (i<L->length && L->data[i]!=e)
        i++;
    if (i>=L->length)
        return 0;
    else
        return i+1;

}

12、插入元素

bool ListInsert(SqList *&L,int i,ElemType e)
{
    int j;
    if (i<1||i>L->length+1)
        return false;
    i--;
    for (j=L->length;j>i;j--)
        L->data[j]=L->data[j-1];
    L->data[i]=e;
    L->length++;
    return true;    
}

13、刪除元素

bool ListDelete(SqList *&L,int i,ElemType &e)
{
    int j;
    if (i<1||i>L->length)
        return false;
    i--;
    e=L->data[i];
    for(j=i;j<L->length-1;j++)
        L->data[j]=L->data[j+1];
    L->length--;
    return true; 

}

線性鏈表

1、單鏈表的存儲結構的定義

typedef struct LNode // 定義單鏈表節點類型
{
    ElemType data; //數據域
    struct LNode *next; //指針域,指向後繼節點  遞歸結構 
}LinkList;

2、單鏈表的頭插法:

void CreateListF(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;
    }   
 } 

3、單鏈表尾插法

void CreateListR(LinkList *&L,ElemType a[],int n)
{
    LinkList *s,*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;
}

4、單鏈表的基本操作

技術分享圖片

5、初始化線性表

void InitList(LinkList *&L)
{
    L=(LinkList *)malloc(sizeof(LinkList));
    L->next=NULL;
}

6、銷毀線性表

void DestroyList(LinkList *&L)
{
    LinkList *pre=L,*p=L->next;
    while (p=NULL)
    {
        free(pre);
        pre=p;
        p=pre->next;
    }
    free(pre);
 } 

7、判斷表為空

bool ListEmpty(LinkList *L)
{
    return(L->next==NULL);
}

8、求線性表的ListLength(L)

 int ListLength(LinkList *L)
 {
    int n=0;
    LinkList *p=L;
    while (p->next!=NULL)
    {
        n++;
        p=p->next;
    }
    return(n);
 }

9、輸出線性表:

void DisList(LinkList *L)
{
    LinkList *p=L->next;
    while(p!=NULL)
    {
        printf("%d",p->data);
        p=p->next;
    }
    printf("\n")
 } 

10、查找某個元素

bool GetElem(LinkList *L,int i,ElemType &e)
 {
    int j=0;
    LinkList *p=L;
    while (j<i&&p!=NULL)
        {
            j++;
            p=p->next;
            }   
    if (p==NULL)
        return false;
    else
    {
        e=p->data;
        return true;
    }
 }

11、 按元素查找,返回元素的位置

 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;
  } 

12、插入數據元素:

     bool ListInsert(LinkList *&L,int i,ElemType e){
    int j=0;
    LinkList *p=L,*S;
    while (j<i-1 && p!=NULL){
        j++;
        p=p->next; 
     }
     if (p==NULL)
         return false;
     else{
        S=LinkList *)malloc(sizeof(LinkList));
        S->data=e;
        S->next=p->next;
        p->next=S;
        return true;    
     }
   }

13、刪除數據元素

 bool ListDelete(LinkList *&L,int i,ElemType &e)
 {
    int j=0;
    LinkList *p=L,*q;
    while(j<i-1 && p!=NULL){
        j++;
        p=p->next;
     }
    if (p==NULL)
        return false;
    else{
        q=p->next;
        if(q=NULL)
            return false;
        e=q->data;
        p->next=q->next;
        free(q);
        return true;
    }
 }

雙鏈表

1、雙向鏈表的定義和存儲結構


 typedef struct DNode
 {
    ElemType data;
    struct DNode *prior;
    struct DNode *next;

 }DLinkList;

2、頭插法建立雙鏈表

{
    DLinkList *S;
    int i;
    L=(DLinkList *)malloc(sizeof(DLinkList));
    L->prior=L->next=NULL;
    for(i=0;i<n;i++)
    {
        S=(DLinkList *)malloc(sizeof(DLinkList));
        S->data=a[i];
        S->next=L->next;
        if(L->next!=NULL)
            L->next->prior=S;
        L->next=S;
        S->prior=L;
     }
 }

3、尾插法建立雙鏈表

 void CreateListR(DLinkList *&L,ElemType a[],int n)
 {
    DLinkList *s,*r;
    int i;
    L=(DLinkList *)malloc(sizeof(DLinkList));
    r=L;
    for (i=0;i<n;i++)
    {
        s=(DLinkList *)malloc(sizeof(DLinkList));
        s->data=a[i];
        r->next=s;
        s->prior=r;
        r=s;
     }
     r->next=NULL;
 }

4、插入節點:

 bool ListInsert(DLinkList *&L,int i,ElemType e)
 {
    int j=0;
    DLinkList *p=L,*s;
    while(j<i-1 && p!=NULL)
    {
        j++;
        p=p->next;
     }
    if (p=NULL)
        return false;
    else 
    {
        s=(DLink *)malloc(sizeof(DLinkList));
        s->data=e;
        s->next=p->next;
        if (p->next!=NULL)
            P->next->prior=s;
        s->prior=p;
        p->next=s;
        return true;
    }
 }

5、雙鏈表刪除節點

 bool ListDelete(DLinkList *&L,int i,ElemType &e)
 {
    int j=0;
    DLinkList *p=L, *q;
    while (j<i-1 && p!=NULL)
    {
        j++;
        p=p->next; 
     } 
    if (p==NULL)
        return false;
    else
    {
        q=p->next;
        if (q==NULL)
            return false;
        e=q->data;
        p->next=q->next;
        if (p->next!=NULL)
            p->next->prior=p;
        free(q);
        return true;

    }
 }

有序表的操作

1、有序順序表的插入操作:

 void ListInsert(SqList *&L,ElemType e)
 {
    int i =0,j;
    while (i<L->length && L->data[i]<e)
        i++;
    for (j=ListLength(L);j>i;j--)
        L->data[j]=L->data[j-1];
    L->data[i]=e;
    L->length++; 
 }

2、有序鏈表的插入操作:

 void ListInsert(LinkList *&L,ElemType e)
 {
    LinkList *pre=L, *p;
    while (pre->next!=NULL && pre->next->data < e)
        pre=pre->next;
    p=(LinkList *)malloc(sizeof(LinkList));
    p->data=e;
    p->next=pre->next;
    pre->next=p;
 }

3、采用順序表存放有序表時的歸並算法(將順序表LA和LB中的元素插入到LC中形成一個新的順序表):

void UnionList(SqList *LA,SqList *LB,SqList *&LC)
{
    int i=0,j=0,k=0;
    LC=(SqList *)malloc(sizeof(SqList));

    // LA和LB均未達到末尾時,擇其小加入LC
    while(i<LA->length && j<LB->length)
    {
        if(LA->data[i]<LB->data[j])
           {
             LC->data[k]=LA->data[i];
             i++;
            }
        else
        {
            LC->data[k]=LB->data[j];
            j++; 
        }
        k++;
    }  

    // LA 尚未掃描完,將其余元素插入LC中
    while(i<LA->length)
    {
        LC->data[k]=LA->data[i];
        i++;
        k++;
     } 

    while(j<LB->length)
    {
        LC->data[k]=LB->data[j];
        j++;
        k++;
    }
}

4、采用單鏈表存放有序表時的歸並算法(將有序鏈表LA和LB中的元素插入到LC中形成一個新的有序鏈表):

void UnionList1(LinkList *LA,LinkList *LB,LinkList *&LC)
{
    LinkList *pa=LA->next, *pb=LB->next, *r,*s;
    LC=(LinkList *)malloc(sizeof(LinkList));
    r=LC;

    // LA 和 LB 均未達到末尾時,擇其小優先尾插

    while(pa!=NULL && pb!=NULL)
    {
        S=(LinkList *)malloc(sizeof(LinkList));
        if(pa->data<pb->data)
        {
            s->data=pa->data;
            pa=pa->next;
        }
        else
        {
            s->data=pb->data;
            pb=pb->next;
        }
        r->next=s;
        r=s;
     } 

     // LA 未達到末尾,復制LA中所有結點
     while(pa!=NULL)
     {
        s=(LinkList *)malloc(sizeof(LinkList));
        s->data=pa->data;
        r->next=s;
        r=s;
        pa=pa->next;
      } 

      // LB 未達到末尾,復制LA中所有結點

     while(pb!=NULL)
     {
        s=(LinkList *)malloc(sizeof(LinkList));
        s->data=pb->data;
        r->next=s;
        r=s;
        pb=pb->next;
      } 
}

棧和隊列

1、棧的判定:

  • 棧空: top = -1
  • 棧滿: top = MaxSize-1
  • 進棧e操作:top ++ ; 將e放在top處
  • 退棧操作:從top處取出元素e; top --;

2、初始化一個空棧s,實際上是將棧頂指針指向-1即可。

// 定義一個順序棧
typedef struct
{
    ElemType data[MaxSize];
        int top;
}SqStack;

void InitStack(SqStack *&s)
{
  s=(SqStack *)malloc(sizeof(SqStack)); // 申請內存空間
    s->top=-1;
}

3、釋放棧s占用的空間,銷毀棧:

void DestoryStack(SqStack *&s)
{
    free(s);
}

4、進棧操作push(&s,e)

  • 條件:在棧不滿時,可以進棧
  • 操作:
    • 將棧指針+1
    • 在該位置上插入元素e
bool Push(SqStack *&s,ElemType e)
{
    if (s->top==MaxSize-1)
        return false;   // 棧滿
        s->top++
        s->data[s->top]=e;
        return true;

}

5、Pop(&s,&e)出棧

  • 條件: 棧不為空
  • 操作:
    • 棧頂元素賦值給e
    • 指針減1
bool Pop(SqStack *&s,ElemType &e)
{

    if (s->top==-1)
            return false;

    e=s->data[s->top];
        s->top--;
        return true;
}

6、用棧判斷對稱串算法

bool summetry(ElemType str[])
{
    int i;
        ElemType e;
        SqStack *st;
        InitStack(st);

        // 將所有元素進棧

        for (i=0;str[i]!=‘\0‘;i++)
            Push(str,str[i]);

        // 出棧的字符與從左向右讀取的字符串比較

        for(i=0;str[i]!=‘\0‘;i++)
        {
        Pop(st,e);
        if(str[i]!=e)
        {
            DestroyStack(st);
                return false;

        }
        }
DestroyStack(st);
return true;

}

棧的鏈式存儲結構

1、棧的鏈式存儲

 *  采用單鏈表: 頭結點後保存棧頂
 *  優點:不存在棧滿上溢的情況
 *  棧空條件: s->next=NULL

定義:

typedef struct linknode
{
    ElemType data;
    struct linknode *next;
 }LiStack;

2、建立一個空棧

void InitStack(LiStack *&s)
{
    s=(LiStack *)malloc(sizeof(LiStack));
    s->next=NULL;
 } 

3、釋放棧的全部占用空間

 void DetroyStack(LiStack *&s)
 {
    LiStack *p=s, *q=s->next;
    while (q!=NULL)
    {
        free(p);
        p=q;
        q=p->next;
     }
     free(p);
 }

4、判斷棧是否為空

 bool StackEmpty(LiStack *S)
 {
    return(s->next==NULL);
 }

5、進棧

 void Push(LiStack *&s,ElemType e)
 {
    LiStack *p;
    p=(LiStack *)malloc(sizeof(LiStack));
    p->data=e;
    p->next=s->next;
    s->next=p;
 }

6、 出棧

 bool Pop(LiStack *&s, ElemType &e)
 {
    LiStack *p;
    if (s->next==NULL)
        return false;
    p=s->next;
    e=p->data;
    s->next=p->next;
    free(p);
    return true;
 }

7、取棧頂元素

 bool GetTop(LiStack *s,ElemType &e)
 {
    if (s->next==NULL)
        return false;
    e=s->next->data;
    return true;
 }

隊列

隊列的數據操作:

  • InitQueue(&q): 初始化隊列,構造一個新隊列
  • DestroyQueue(&q): 銷毀隊列。
  • QueueEmpty(q):判斷隊列是否為空
  • enQueue(&q,e): 進隊列。將元素e進隊,作為隊尾元素。
  • deQueue(&q,&e): 出隊列。

隊列的存儲結構:

  • 數據元素data : 元素具有同一類型ElemType.最多Maxsize
  • 當前隊首: front
  • 當前隊尾:rear

定義結構:

typedef struct
{
    ElemType data[MaxSize];
    int front,rear; //隊首和隊尾指針 
 } SqQueue; 

1、順序隊的特性

  • 隊空條件: front = rear
  • 隊滿條件: rear = MaxSize - 1
  • 元素e進隊: rear ++; data[rear]=e;
  • 元素e出隊: front ++; e=data[front];
  • rear指向隊尾元素
  • front指向隊頭元素的前一個位置

2、初始化隊列

 void InitQueue(SqQueue *&q)
 {
    q=(SqQueue *)malloc(sizeof(SqQueue));
    q->front=q->rear=-1;
  }

3、釋放隊列q所占的存儲空間

  void DestroyQueue(SqQueue *&q)
  {
    free(q);
  }

4、判斷隊列是否為空QueueEmpty

bool QueueEmpty(SqQueue *q)
{
    return(q->front==q->rear);
}

5、進隊列

bool enQueue(SqQueue *&q,ElemType e)
{
    if (q->rear==MaxSize-1)
    return false;
    q->rear++
    q->data[q->rear]=e;
    return true;
}

6、出隊列

bool deQueue(SqQueue *&q,ElemType &e)
{
    if (q->front==q->rear)
        return false;
    q->front++;
    e=q->data[q->front];
    return true;
}

提示:順序隊列在滿隊數據取完後,在隊空的情況下會出現front==rear&& rear = MaxSize - 1的情況,而出現這種情況後,無法再插入數據,這就需要使用環形隊列。

環形隊列

  • 隊空條件: front=rear
  • 隊滿條件:(rear+1)%MaxSize=front
  • 進隊e操作: rear=(rear+1)%MaxSize; 將e放在rear處
  • 處隊操作:front=(front+1)%MaxSize; 取出front處元素e;

數據結構基礎(一)