其他分享
首页 > 其他分享> > 线性数据结构

线性数据结构

作者:互联网

目录

一、线性表及其实现

1、多项式的表示

方法1:顺序存储结构直接表示

方法2:顺序存储结构表示非零项

方法3:链表结构存储非零项

2、什么是线性表

3、线性表的顺序存储实现

3.1初始化(建立空的顺序表)

3.2查找

3.3插入

3.4删除

4、线性表的链式存储实现

4.1求表长

4.2查找

4.3插入

4.4删除

4.5案例:单链表的逆转

5、广义表

6、多重链表

二、堆栈

1、什么是堆栈

2、栈的顺序存储实现

2.1一个数组实现一个堆栈

2.2一个数组实现两个堆栈

3、堆栈的链式存储实现

4、堆栈应用:表达式求值

三、队列

1、什么是队列

2、队列的顺序存储实现

3、队列的链式存储实现

4、应用实例:多项式加法运算

5、多项式的相乘和相加运算

5.1题意理解

5.2求解思路


一、线性表及其实现

1、多项式的表示

【例】一元多项式及其运算

一元多项式:f(X) = a_0 + a_1x+\cdots+a_{n-1}x^{n-1} + a_nx^n

主要运算:多项式相加、相减、相乘等

【分析】多项式的关键数据:

多项式项数n
各项系数a_i及指数i

方法1:顺序存储结构直接表示

数组各分量对应多项式各项:

a[i]:项xi的系数ai

例如: f(X) = 4x^5-3x^2+1

表示成:

 两个多项式相加:两个数组对应分量相加

方法2:顺序存储结构表示非零项

每个非零项 a_ix^i 涉及两个信息:系数 a_i 和指数 i 

可以将一个多项式看成是一个 (a_i,i) 二元组的集合。

用结构数组表示:数组分量是由系数 a_i、指数 i 组成的结构,对应一个非零项

例如:P_1(x)=9x^{12}+15x^7+3x^2 和 P_2(x)=26x^{19}-4x^8-13x^6+82

 相加过程:可以从头开始,比较两个多项式当前对应项的指数

方法3:链表结构存储非零项

链表在每个结点存储多项式中的一个非零项,包括系数和指数两个数据域以及一个指数域

结点:

Struct PolyNode
{
    int coef;
    int expon;
    Polynomial link;
}

PolyNode* Polynomial;

【链表存储形式】

 

2、什么是线性表

3、线性表的顺序存储实现

利用数组的连续存储空间顺序存放相信白哦的各元素

sruct LNode
{
	ElementType Data[MAXSIZE];
    int Last;
}

LNode L;
LNode* PtrL = &L;

访问下标为 i 的元素:L.Data[i] 或 PtrL->Data[i]

线性表的长度: L.Last+1 或 PtrL->Last+1

主要操作的实现

3.1初始化(建立空的顺序表)

LNode* MakeEmpty()
{
	LNode* PtrL = new LNode(sizeof(struct LNode));
    PtrL->Last = -1;
    return PtrL;
}

3.2查找

int Find(ElementType X, List PtrL)
{
	int i = 0;
    while (i <= PtrL->Last && PtrL->Data[i] != X)
    {
        i++;
	}
    //如果没有找到,返回-1
    if (i > PtrL->Last)
    {
        return -1;
    }
    else if
    {
        //找到后返回存储位置
        return i;
	}
}

查找成功的平均次数为(n+1)/2,平均时间性能为O(n)

3.3插入

i(1\leq i \leq n+1) 个位置上插入一个值为X的新元素

 

void Insert(ElementType X, int i, List PtrL)
{
	if (PtrL->Last == MAXSIZE - 1)
    {
        cout << "表满" << endl;
        return;
	}
    if (i < 1 || i > PtrL->Last + 2)
    {
        cout << "位置不合法" << endl;
        return;
	}
    for (int j = PtrL->Last; j >= i - 1; j--)
    {
        PrtL->Data[j + 1] = PtrL->Data[j];
        PrtL->Data[i - 1] = X;
        PrtL->Last++;
        return;
	}
}

平均移动次数为n/2,平均时间性能为O(n)

3.4删除

删除表的第 i(1 \leq i \leq n) 个位置上的元素

 

void Delete(int i, List PtrL)
{
	if (i < 1 || i > PtrL->Last + 1)
    {
        cout << "不存在该元素" << endl;
        return;
    }
    for (int j = i; j <= PtrL->Last; j++)
    {
        PtrL->Data[j - 1] = PtrL->Data[j];
        PtrL->Laast--;
	}
    return;
}

平均移动次数为(n-1)/2,平均时间习能为O(n)

4、线性表的链式存储实现

不要求逻辑上相邻的两个元素物理上也相邻;通过“链”建立起数据元素之间的逻辑关系。

故插入、删除不需要移动数据元素,只需要修改“链”。

struct LNode
{
	ElementType Data;
    List Next;
}

LNode L;
LNode* PtrL = &L;

 主要操作的实现:

4.1求表长

int Length(LNode* PtrL)
{
    LNode* p = PtrL;
    int j = 0;
    while (p)
    {
        p = p->Next;
        j++;
	}
    return j;
}

时间性能为O(N)

4.2查找

LNode* FindKth(int K, LNode* PtrL)
{
	LNode* p = PtrL;
    int i = 1;
    while (p != NULL && i < K)
    {
        p = p->Next;
        i++;
	}
    if (i == K)
    {
        return p;
	}
    else
    {
        return NULL:
	}
}

LNode* Find(ElementType X, LNode* PtrL)
{
    LNode* p = PtrL;
    while (p != NULL && p->Data != X)
    {
        p = p->Next;
	}
    return p;
}

平均时间性能O(N)

4.3插入

 

LNode* Insert(ElementType X, int i, LNode* PtrL)
{
    LNode* p, s;
    if (i == 1)
    {
        s = new LNode(Data = X, Next = PrtL);
        return s;
	}
    p = FindKth(i - 1, PtrL);
    if (p == NULL)
    {
        cout << "参数 i 错误" << endl;
        return NULL;
	}
    else
    {
        s = new LNode(Data = X, Next = PrtL);
        p->Next = s;
        return PtrL;
	}
}

平均查找次数为n/2,平均时间性能为O(n)

4.4删除

 

LNode* Delete(int i, LNode* PtrL)
{
    LNode* p, s;
    if (i == 1)
    {
        s = PtrL;
        if (PtrL != NULL)
        {
            PtrL = PtrL->Next;
		}
        else
        {
            return NULL;
		}
        return PtrL;
	}
    
    p = FindKth(i - 1, PtrL);
    if (p == NULL)
    {
        cout << "不存在i-1该元素" << endl;
        return NULL;
	}
    else if (p->Next == NULL)
    {
        cout << "不存在i该元素" << endl;
        return NULL:
	}
    else
    {
        s = p->Next;
        p->Next = s->Next;
        return PtrL;
	}
}

平均查找次数为n/2,平均时间性能为O(n)

4.5案例:单链表的逆转

 

//伪代码
Ptr reverseL(Ptr head, int K)
{
    cnt = 1;
    new = head->next;
    old = new->next;
    while (cnt < K)
    {
        tmp = old->next;
        old->next = new;
        new = old;
        old = tmp;
        cnt++;
    }
    head->next->next = old;
    return new;
}

5、广义表

 

 

6、多重链表

 

 

 

二、堆栈

1、什么是堆栈

2、栈的顺序存储实现

2.1一个数组实现一个堆栈

#define MaxSize 存储数据元素的最大个数

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

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

ElementType Pop(Stack PtrS)
{
    if (PtrS->Top == -1)
    {
        cout << "堆栈空" << endl;
        return ERROR; 
        //ERROR是ElementType的特殊值,标志错误
	}
    else
    {
        return (PtrS->Data[(PtrS->Top)--]);
	}
}

2.2一个数组实现两个堆栈

#define MaxSize 存储数据元素的最大个数

struct DStack
{
	ElementType Data[MaxSize];
    int Top1;
    int Top2;
}S;

S.Top1 = -1;
S.Top2 = MaxSize;

void Push(DStack* PtrS, ElementType item, int Tag)
{
    //Tag作为区分两个堆栈的标志,取值为1和2
    if (PtrS->Top2 - PtrS->Top1 == 1)
    {
        cout << "堆栈满" << endl;
        return;
	}
    
    if (Tag == 1)
    {
        PtrS->Data[++(PtrS->Top1)] = item;
	}
    else
    {
        PtrS->Data[--(PtrS->Top2)] = item;
	}
}

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

3、堆栈的链式存储实现

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

Stack CreateStack()
{
    Stack S = new SNode;
    S->Next = NULL;
    return s;
}

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

void Push(ElementType item, Stack S)
{
    Stack TmpCell = new SNode;
    TemCell->Element = item;
    TemCell->Next = S->Next;
    S->Next = TmpCell;
}

ElementType Pop(Stack S)
{
    Stack FirstCell;
    ElementType TopElem;
    if (IsEmpty(S))
    {
        cout << "堆栈空" << endl;
        return NULL:
    }
    else
    {
        FirstCell = S->Next;
        S->Next = FirstCell->Next;
        TopElem = FirstCell->Element;
        return TopElem;
    }
}

4、堆栈应用:表达式求值

 

三、队列

1、什么是队列

2、队列的顺序存储实现

一个正常的工作队列

 

 

顺环队列

该结构可以循环使用,对应的要空出一个位置当作那个位置为-1的空间

 

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

这里使用求模的技巧实现顺环结构的队列

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

3、队列的链式存储实现

 

 

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

Queue creatQueue()
{
    Queue PtrQ;
    return PtrQ;
}

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

void AddQ(ElementType item, Queue PtrQ)
{
    Node* RearCell;
    RearCell->Data = item;
    RearCell->Next = NULL;
    
    if (PtrQ->front == PtrQ->rear)
    {
        PtrQ->front = RearCell;
        PtrQ->rear = RearCell;
        return;
    }
    
    PtrQ->rear->Next = RearCell;
    PtrQ->rear = RearCell;
}

4、应用实例:多项式加法运算

主要思路:相同指数的项系数相加,其余部分进行拷贝

案例:采用不带头结点的单向链表,按照指数递减的顺序排列各项

算法思路:两个指针P1和P2分别指向这两个多项式第一个结点,不断循环:

struct PolyNode
{
    int coef;
    int expon;
    PolyNode* Next;
};

typedef PolyNode* Polynomial;
Polynomial P1, P2;

Polynomial PolyAdd(Polynomial P1, Polynomial P2)
{
    Polynomial front, rear;
    rear = new PolyNode;
    front = rear;
    int sum;
    
    //P1与P2两个都不为空时,一直执行
    while (P1 && P2)
    {
        //compare比较大小
        switch (compare(P1->expon, P2->expon))
        {
                //P1的指数大,返回1
            case 1:
                attach(P1->coeef, P1->expon, &rear);
                //修改P1指向,往下执行
                P1 = P1->Next;
                break;
                //P2的指数大,返回-1
            case -1:
                attach(P2->coef, P2->expon, &rear);
                //修改P2指向,往下执行
                P2 = P2->Next;
                break;
                //P1和P2的指数相等,返回0
            case 0:
                sum = P1->coef + P2->coef;
                //如果系数相加不为0,则创建新结点
                if (sum != 0)
                {
                    attach(sum, P1->expon, &rear)
                }
                P1 = P1->Next;
                P2 = P2->Next;
                break;
        }
    }
    
    //未处理完的多项式
    for (; P1; P1 = P1->Next)
    {
        attach(P1->coef, P1->expon, &rear);
    }
    
    for (; P2; P2 = P2->Next)
    {
        attach(P2->coef, P2->expon, &rear);
    }
    
    //将最后一个结点的链表指向设为NULL
    rear->Next = NULL;
    //将空结点舍弃,直接指向多项式首结点
    front = front->Next;
    return front;
}

void attach(int c, int e, Polynomial* pRear)
{
    //这里的pRear相当于二级指针
    
    //创建新结点
    Polynomial p = new PolyNode;
    
    //为新结点赋值
    p->coef = c;
    p->expon = e;
    p->Next = NULL;
    
    //让上一个结点的指针域指向新结点
    //修改rear的指向
    (*pRear)->Next = p;
    *pRear = p;
}

 

5、多项式的相乘和相加运算

5.1题意理解

 

5.2求解思路

typedef PolyNode* Polynomial;
struct PolyNode
{
    int coef;
    int expon;
    Polynomial Next;
}

2、程序框架搭建

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

3、如何读入多项式

Polynomial readPoly()
{
    Polynomial P, rear;
    int c, e, n;
    
    P = new PolyNode;
    P->Next = NULL;
    rear = P;
    
    cout << "多项式的项数为: " << endl;
    cin >> n;
    
    cout << "按幂指数由大到小的顺序输入: " << endl;
    while (n--)
    {
        cout << "请分别输入该项的系数与指数: "  << endl;
        cin >> c;
        cin >> e;
        
        attach(c, e, rear);
    }
    
    P = P->Next;
    return P;
}

void attach(itn c, int e, Polynomial& rear)
{
    Polynomial P = new PolyNode;
    P->c = c;
    P->e = e;
    P->Next = NULL;
    
    rear->Next = P;
    rear = P;
}

4、如何将两个多项式相加

Polynomial add(Polynomial P1, Polynomial P2)
{
    Polynomial P = new PolyNode;
    P->Next = NULL:
    Polynomial rear = P;
    int sum;
    
    while (P1 && P2)
    {
        switch(compare(P1->expon, P2->expon))
        {
            case 1:
                attach(P1->coef, P1->expon, rear);
                P1 = P1->Next;
                break;
            case -1:
                attach(P2->coef, P2->expon, rear);
                P2 = P2->Next;
                break;
            case 0:
                sum = P1->coef + P2->coef;
                if (sum)
                {
                    attach(sum, P1->expon, rear);
                    P1 = P1->Next;
                    P2 = P2->Next;
                }
                break;
        }
    }
    
    while(P1)
    {
        attach(P1->coef, P1->expon, rear);
        P1 = P1->Next;
    }
    
    while(P2)
    {
        attach(P2->coef, P2->expon, rear);
        P2 = P2->Next;
    }
    
    P = P->Next;
    return P;
    
}

5、如何将两个多项式相乘

Polynomial mult(Polynomial P1, Poltnomial P2)
{
    if (!P1 || !P2)
    {
        return NULL;
    }
    
    Polynomial P, rear, t1, t2;
    int c, e;
    
    P = new PolyNode;
    P->Next = NULL;
    rear = P;
    
    t1 = P1;
    t2 = P2;
    
    while (t2)
    {
        //创建初始结果多项式
        attach(t1->coef * t2->coef, t1->expon + t2->expon, rear);
        t2 = t2->Next;
    }
    
    t1 = t1->Next;
    while (t1)
    {
        t2 = P2;
        rear = P;
        
        while (t2)
        {
            c = t1->coef * t2->coef;
            e = t1->expon + t2->expon;
            
            //找出rear->Next->expon的值小于等于e
            while (rear->Next && rear->Next->expon > e)
            {
                rear = rear->Next;
            }
            
            //判断是小于或是等于的情况
            if (rear->Next && rear->Next->expon == e)
            {
                //判断coef值是否为零
                if (rear->Next->coef + c)
                {
                    rear->Next->coef += c;
                }
                else
                {
                    rear->Next = rear->Next->Next; 
                }
            }
            else
            {
                //若是小于的情况,创建新结点插入
                Polynomial t = new PloyNode;
                t->coef = c;
                t->expon = e;
                t->Next = rear->Next;
				rear->Next = t;
            }
            
            t2 = t2->Next;
        }
        
        t1 = t1->Next;
    }
    
    P = P->Next;
    return P;
}

void printPoly(Polynomial P)
{
    if (!P)
    {
        cout << "0" << endl;
        return;
    }
    
    while (P)
    {
        cout << P->coef << " " 
            << P->expon << " ";
        P = P->Next;
    }
    cout << endl;
}

标签:P2,P1,int,Next,PtrL,线性,数据结构,rear
来源: https://blog.csdn.net/weixin_38872229/article/details/120914563