第二课:线性表

线性表的链式存储结构及基本操作

typedef struct LNode *List;
struct LNode{
    ElementType Data;
    List Next;
};
struct LNode L;
List PtrL;

1、求表长

int Length(List PtrL)
{
    List p = PtrL;
    int j = 0;
    while (p) {
        p = p->next;
        j++;
    }
    return j;
}

2、查找

  • 按序号查找
List FindKth(int K,List PtrL)
{
    List p = PtrL;
    int i = 1;
    while (p != NULL && i < K) {
        p = p->next;
        i++;
    }
    if (i == K)
        return p;
    else
        return NULL;
  • 按值查找
List Find(ElementType X,List PtrL)
{
    List p = PtrL;
    while (p != NULL && p->Data != X)
        p = p->Next;
    return p;
}

3、插入操作实现

List Insert(ElementType X,int i,List PtrL)
{
    List p,s;
    if (i == 1) {
        s = (List)malloc(sizeof(struct LNode));
        s->Data = X;
        s->next = PtrL;
        return s;
    }
    p = FindKth(i - 1,PtrL);
    if (p == NULL) {
        printf("参数i错");
        return NULL;
    } else {
        s = (List)malloc(sizeof(struct LNode));
        s->Data = X;
        s->next = p->next;
        p->next = s;
        return PtrL;
    }
}

4、删除

List Delete(int i,List PtrL)
{
    List p,s;
    if (i == 1) {
        s = PrrL;
        if (PtrL != NULL)
            PtrL = PtrL->next;
        else
            return NULL;
        free(s);
        return PtrL;
    }
    p = FindKth(i - 1,PtrL);
    if (p == NULL) {
        printf("第%d个节点不存在",i - 1);
        return NULL;
    } else if (p ->next == NULL) {
        printf("第%d个节点不存在",i);
        return NULL;
    } else {
        s = p->Next;
        p->Next = s->next;
        free(s);
        return PtrL;
    }
}

广义表

typedef struct GNode *GList;
struct GNode{
    int Tag;
    union {
        ElementType Data;
        GList SubList;
    }URegion;
    GList Next;
}

多重链表表示稀疏矩阵

堆栈:后入先出

 

栈的顺序存储实现

栈的顺序存储结构通常由一个一维数组和一个记录栈顶元素位置的变量组成

#define MaxSize <储存数据元素的最大个数>
typedef struct SNode *Stack;

struct SNode{
    ElementType Data[MaxSize];
    int Top;
};

1、入栈:

void Push(Stack PtrS,ElementType item)
{
    if (PtrS->Top == MaxSize - 1) {
        printf("堆栈满");
        return;
    } else {
        PtrS->Data[++(PtrS->Top)] = item;
        return;
    }
}

2、出栈

ElementType Pop(Stack PtrS)
{
    if (PtrS->Top == -1) {
        printf("堆栈空");
        return ERROR;
    } else {
        return PtrS->Data[(PtrS->Top)--]);
    }
}

只用一个数组实现两个堆栈,只要有空间,入栈操作就可以成功

#define MaxSize <存储数据元素的最大个数>
struct DStark{
    ElemntType Data[MaxSIze];
    int Top1;
    int Top2;
}S;
S.Top1 = -1;//第一个堆栈为空
S.Top2 = MaxSize;//第二个堆栈为空

1、入栈

void Push(struct DStack *PtrS,ElementType item,int Tag)
{
    if (PtrS->Top2 - PtrS->Top == 1) {
        printf("堆栈满");
        return;
        }
    if (Tag == 1)
        PtrS->Data[++(PtrS->Top1)] = item;
    else
        PtrS->Data[--(PtrS->Top2)] = item;
}

2、出栈

ElementType Pop(struct DStack *PtrS,int Tag)
{
    if (Tag == 1) {
        if (PtrS->Top1 == -1) {
            printf("堆栈1空");
            return NULL;
        } else {
            return PtrS->Data[(PtrS->Top1)--];
        }
    } else {
        if (PtrS->Top2 == MaxSize) {
            printf("堆栈2空");
            return NULL;
        } else {
            return PtrS->Data[(PtrS->Top2)++];
        }
    }
}

堆栈的链式存储实现

typedef struct SNode *Stack;
struct SNode {
    ElemenType Data;
    struct SNode *Next;
};

1、堆栈初始化

Stack CreateStack()
{
    Stack S;
    S = (Stack)malloc(sizeof(struct SNode));
    S->Next = NULL;
    return S;
}

2、判断堆栈是否为空

int IsEmpty(Stack S)
{
    return (S->Next == NULL);
}

3、Push

void Push(ElementType item,Stack S)
{
    struct SNode *TmpCell;
    TmpCell = (struct SNode *)malloc(sizeof(struct SNode));
    TmpCell->Element = item;
    TmpCell->next = S->Next;
    S->Next = TmpCell;
}

4、pop

ElemetType Pop(Stack S)
{
    struct SNode *FirstCell;
    ElementType TopElem;
    if (IsEmpty(S)) {
        printf("堆栈空");
        return NULL;
    } else {
        FirstCell = S->Next;
        S->Next = FirstCell->Next;
        TopElem = FirstCell->Element;
        free(FirstCell);
        return TopElem;
    }
}

中缀表达式求值

1、运算数相对顺序不变

2、运算符号顺序发生改变

  • 需要存储“等待中”的运算符号
  • 要将当前运算符号与“等待中”的最后一个运算符号比较

有括号

队列的顺序存储实现

#define MaxSize <储存数据元素的最大个数>
struct QNode{
    ElementType Data[MaxSize];
    int rear;
    int front;
};
typedef struct QNode *Queue;

1、入队列

void AddQ(Queue PtrQ,ElementType item)
{
    if ((PtrQ->rear + 1) % MaxSize == PtrQ->front) {
        printf("队列满");
        return;
    }
    PtrQ->rear = (PtrQ->rear + 1) % MaxSIze;
    PtrQ->Data[PtrQ->rear] = item;
}

2、出队列

ElementType DeleteQ(Queue PtrQ)
{
    if (PtrQ->front == PtrQ->rear) {
        printf("队列空");
        return ERROR;
    } else {
        PtrQ->front == (PtrQ->front + 1) % MaxSize;
        return PtrQ->Data[PtrQ->front];
    }
}

链表的链式存储实现

struct Node{
    ElementType Data;
    struct Node *Next;
};
struct QNode{
    struct Node *rear;
    struct Node *front;
};
typedef struct QNode *Queue;
Queue PtrQ;

出队

ElementType DeleteQ(Queue PtrQ)
{
    struct Node *FrontCell;
    ElementType FrontElem;
    
    if (PtrQ->front == NULL) {
        printf("队列空");
        return ERROR;
    }
    FrontCell = PtrQ->front;
    if (PtrQ->front == PtrQ->rear)
        PtrQ->front = PtrQ->rear = NULL;
    else
        PtrQ->front = PtrQ->front->Next;
    FrontElem = FrontCell-<Data;
    free(FrontCell);
    return FrontElem;
}

创建新节点

typedef struct Node QNode;
static QNode *BuyQNode(ElementType data)
{
    QNode *TmpNode = (QNode *)malloc(sizeof(QNode));
    if (NULL == TmpNode)
    {
        printf("申请空间失败!\n");
    }
    TmpNode->data = data;
    TmpNode->Next = NULL;
    
    return TmpNode;
}

队列初始化

void QueueInit(Queue *q)
{
    q->front = q->rear = NULL;
}

 入队列

void QueuePush(Queue *q,ElementType data)
{
    if (NULL == q->front)
    {
        q->front = q->rear = BuyQNode(data);
        return;
    }
    q->rear->Next = BuyQNode(data);
    q->rear = q->rear->Next;
}

多项式加法运算

struct PolyNode{
    int coef;
    int coef;
    int expon;
    struct PolyNode *link;
};
typedef struct PolyNode *Polynomial;
Polynomial P1,P2;
Polynomial PolyAdd(Polynomial P1,Polynomial P2)
{
    Polynomial front,rear,temp;
    rear = (Polynomial)malloc(sizeof(struct PolyNode));
    front = rear;
    while(P1 && P2)
    {
        switch(Compare(P1->expon,P2->expon)) {
            case 1:
                Attach(P1->coef,P1->expon,&rear);
                P1 = P1->link;
                break;
            case -1:
                Attach(P2->coef,P2->expon,&rear);
                P2 = P2->link;
                break;
            case 0:
                sum = P1->coef + P2->coef;
                if (sum)
                {
                    Attach(sum,P1->expon,&rear);
                }
                P1 = P1->link;
                P2 = P2->link;
                break;
        }
    }
    for (;P1;P1 = P1->link)
    {
        Attach(P1->coef,P1->expon,&rear);
    }
    for (;P2;P2 = P2->link)
    {
        Attach(P2->coef,P2->expon,&rear);
    }
    rear->link = NULL;
    temp = front;
    front = front->link;
    free(temp);
    return front;
}
void Attach(int c,int e,Polynomial *pRear)
{
    Polynimial P;
    
    P = (Polynomial)malloc(sizeof(struct PolyNode));
    P->coef = c;
    P_>expon = e;
    P->link = NULL;
    (*pRear)->link = P;
    *pReaR = p;
}

多项式的乘积

typedef struct PolyNode *Polynomial;
struct PolyNode{
    int coef;
    int expon;
    Polynomial link;
};
int main()
{
    Polynomial P1,P2,PP,PS;
    
    P1 = ReadPoly();
    P2 = ReadPoly();
    PP = Mult(P1,P2);
    PrintPoly(PP);
    PS = Add(P1,P2);
    PrintPoly(PS);
    
    return 0;
}
Polynomial ReadPoly()
{
    Polynomial P,Rear,t;
    int c,e,N;
    
    scanf("%d",&N);
    P = (Polynomial)malloc(sizeof(struct PolyNode));
    P->link = NULL;
    Rear = P;
    
    while(N--) {
        scanf("%d %d",&c,&e);
        Attach(c,e,&Rear);
    }
    
    t = P;P = P->link;free(t);
    return P;
}
void Attach(int c,int e,Polynomial *pRear)
{
    Polynomial P;
    
    P = (Polynomial)malloc(sizeof(struct PolyNode));
    P->coef = c;
    P->expon = e;
    P->link = NULL;
    (*pRear)->link = P;
    *pRear = P;
}

 

void PrintPoly(Polynomial P)
{
    int flag = 0;
    
    if (!P) {
        printf("0 0\n");
        return;
    }
    
    while (P) {
        if (!flag)
        {
            flag = 1;
        }
        else
        {
            printf(" ");
        }
        printf("%d %d",P->coef,P->expon);
        P = P->link;
    }
}

分层次组织在管理上具有更高的效率

静态查找

方法一:顺序查找

int SequentialSearch(List Tbl,ElementType K)
{
    int i;
    Tbl->Element[0] = K;
    for (i = Tbl->Length;Tbl->Element[i] != K;i--)
        ;
    return i;
}
typedef struct LNode *List;
struct LNode {
    ElementType Element[MAXSIZE];
    int length;
};

方法二:二分查找

int BinarySearch(List Tbl,ElementType K)
{
    int left,right,mid,NotFound = -1;
    
    left = 1;
    right = Tbl->Length;
    while (left <= right)
    {
        mid = (left + right) / 2;
        if (K < Tbl->Element[mid])
        {
            right = mid - 1;
        }
        else if (K < Tbl->Element[mid])
        {
            right = mid - 1;
        }
        else if (K > Tbl->Element[mid])
        {
            left = mid + 1;
        }
        else
        {
            return mid;
        }
        return NotFound;
    }
}

查找树

树的一些基本术语

1、结点的度:结点的子数个数

2、树的度:树的所有节点中最大的度数

3、叶结点:度为0的结点

4、父结点:有子树的结点是其子树的根结点的父结点

5、子结点:若A结点是B的父结点,则称B结点是A结点的子结点;子结点也称孩子结点。

6、兄弟结点:具有同一父结点的各结点彼此是兄弟结点。

7、路径和路径长度:从结点n1,n2,.......,nK,ni是ni+1的父结点。

8、路径所含边的个数为路径的长度。

9、祖先结点:沿树根到某一结点路径上的所有结点都是这个结点的祖先结点。

10、子孙结点:某一结点的子树中的所有结点是这个结点的子孙。

11、结点的层次:规定根结点在1层,其他任一结点的层数是其父节点的层数加1。

12、树的深度:树中所有结点的最大层次是这棵树的深度。

树的表示

二叉树几个重要性质

一个二叉树第i层的最大节点数为:2i-1,i>=1

深度为k的二叉树有最大结点总数:2k - 1,k>=1

对任何非空二叉树T,若n0表示叶节点的个数,n2是度为2的非叶结点个数,那么两者满足关系n0 = n2 + 1

typedef struct TreeNode *BinTree;
typedef BinTree Position;
struct TreeNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
};

 二叉树的遍历

先序遍历

遍历过程为:

访问根节点;

1、先序遍历其左子树;

2、先序遍历其右子树。

void PreOrderTraversal(BinTree BT)
{
    if (BT) {
        printf("%d",BT->Data);
        PreOrderTraversal(BT->Left);;
        preOrderTraversal(BT->Right);
    }
}

中序遍历

1、中序遍历其左子树;

2、访问根节点;

3、中序遍历其右子树;

void PreOrderTraversal(BinTree BT)
{
    if (BT) {
        PreOrderTraversal(BT->Left);
        printf("%d",BT->Data);
        preOrderTraversal(BT->Right);
    }
}
void PreOrderTraversal(BinTree BT)
{
    if (BT) {
        PreOrderTraversal(BT->Left);
        preOrderTraversal(BT->Right);
        printf("%d",BT->Data);
    }
}

中序遍历非递归遍历算法

void InOrderTraversal(BinTree BT)
{
    BinTree T = BT;
    Stack S = CreaStack(MaxSize);
    while (T || !IsEmpty(S)) {
        while (T)
        {
            Push(S,T);
            T = T->Left;
        }
        if (!IsEmpty(S)) {
            T = Pop(S);
            printf("%5d",T->Data);
            T = T->Right;
        }
    }
}

先序

void InOrderTraversal(BinTree BT)
{
    BinTree T = BT;
    Stack S = CreaStack(MaxSize);
    while (T || !IsEmpty(S)) {
        while (T)
        {
            Push(S,T);
            printf("%5d",T->Data);
            T = T->Left;
        }
        if (!IsEmpty(S)) {
            T = Pop(S);
            T = T->Right;
        }
    }
}

后序

void PostOrderTraversal(Bintree BT)
{
    Bintree T = BT;
    Bintree flag = NULL;
    Bintree top;
    Stack S = CreateStack(MaxSize);
    while (T || !IsEmpty(S))
    {
        while (T)
        {
            push(S,T);
            T = T->Left;
        }
    
        top = GetTop(S);
    
        if (top->Right == NULL || top->Right == flag)
        {
            printf("% 5d",top->Data);
            flag = pop(s);
        }
        else
        {
            T->Right;
        }
    }
}

层序基本过程:

void LevelOrderTraversal(BinTree BT)
{
    Queue Q;
    BinTree T;
    if (!BT)
        return;
    Q = CreatQueue(MaxSize);
    AddQ(Q,BT);
    while (!IsEmptyQ(Q)) {
        T = DeleteQ(Q);
        printf("%d\n",T->Data);
        if (T->Left)
        {
            AddQ(Q,T->Left);
        }
        if (T->Right)
        {
            Add(Q,T->Right);
        }
    }
}

输出二叉树中的叶子结点

void PreOrderPrintLeaves(BinTree BT)
{
    if (BT) {
        if (!BT->Left && !BT->Right)
        {
            printf("%d",BT->Data);
        }
        PreOrderPrintLeaves(BT->Left);
        PreOrderPrintLeaves(BT->Right);
    }
}

求二叉树的高度

int PostOrderGetHeight(BinTree BT)
{
    int HL,HR,MaxH;
    if (BT) {
        HL = PostOrderGetHeight(BT->Left);
        HR = PostOrderGetHeight(BT->Right);
        MaxH = (HL > HR) ? HL : HR;
        return(MaxH + 1);
    }
    else
        return 0;
}

有两种遍历序列确定二叉树必须要有中序序列。

二叉树的表示:

#define MaxTree 10
#define ElementType char
#define Tree int
#define Null -1

struct TreeNode
{
    ElementType Element;
    Tree Left;
    Tree Right;
}T1[MaxTree],T2[MaxTree];

程序框架搭建

int main()
{
    Tree R1,R2;
    
    R1 = BuildTree(T1);
    R2 = BuildTree(T2);
    
    if (Isomorphic(R1,R2))
        printf("Yes\n");
    else
        printf("No\n");
    return 0;
}

如何建二叉树

int Isomorphic(Tree R1,Tree R2)
{
    if ((R1 == Null) && (R2 == NULL))
        return 1;
    if (((R1 == Null) && (R2 != Null)) || (R1 != Null))
        return 0;
    if (T1[R1].Element != T2[R2].Element)
        return 0;
    if ((T1[R1].Left == NUll) && T2[R2].Left == NULL)
        return Isomorphic(T1[R1].Right,T2[R2].Right);
    if(((T1[R1].Left != Null) && (T2[R2].Left != Null)
         ((T1[T1[R1].Left].Element) == T2[T2[R2].Left].Element))
        return(Isomorphic(T1[R1].Left,T2[R2].Left) && 
               Isomorphic(T1[R1].Right,T2[R2].Right));
    else
        return(Isomorphic(T1[R1].Left,T2[R2].Right) && 
               Isomorphic(T1[R1].Right,T2[R2].Left));
}

二叉搜索树

Position FInd(ElementType X,BinTree BST)
{
    if (!BST)
        return NULL;
    if (X > BST->Data)
        return Find(X,BST->Right);
    else if (X < BST->Data)
        return FInd(X,BST->Left);
    else
        return BST;
}
Position IterFInd(ElementType X,BinTree BST)
{
    while (BST) {
        if (X > BST->Data)
            BST = BST->Right;
        else if (X < BST->Data)
            BST = BST->Left;
        else
            return BST;
    }
    return NULL;
}
Position FindMin(BinTree BST)
{
    if (!BST)
        return NULL;
    else if (!BST->Left)
        return BST;
    else
        return FIndMin(BST->Left);
}
Position FindMax(BinTree BST)
{
    if (BST)
        while(BST->Right)
            BST = BST->Right;
    return BST;
}

二叉搜索树的插入

BinTree Insert(ElementType X,BinTree BST)
{
    if (!BST) {
        BST = malloc(sizeof(struct TreeNode));
        BST->Data = X;
        BST->Left = BST->Right = NULL;
    } else {
        if (X < BST->Data){
            BST->Left = Insert(X,BST->Left);
        } else if (X > BST->Data) {
            BST->Right = Insert(X,BST->Righe);
        }
    }
    return BST;
        
}

二叉搜索树的删除

BinTree Delete(ElementType X,BinTree BST)
{
    Position Tmp;
    if (!BST)
        printf("要删除的元素未找到");
    else if (X < BST->Data)
        
}

 

posted @ 2023-08-03 20:52  海晨  阅读(21)  评论(0)    收藏  举报