线性表及其实现
线性表是由同类型数据元素构成的有序序列的线性结构。线性表的基本操作:插入,删除,查找。线性表中可以没有元素时,称为空表。
线性表可以用来表示多项式的加减乘等。
线性表的实现方式有两种,一种线性表的顺序存储实现,一种是线性表的链式存储实现。
线性表的顺序存储实现
List MakeEmpty()
{
List L;
L = (List)malloc(sizeof(struct LNode));
L->Last = -1;
return L;
}
查找:查找有两种,一种是按照序号查找,一种是按值查找。
Position Find( List L, ElementType X )
{
Position i = 0;
while( i <= L->Last && L->Data[i]!= X )
i++;
if ( i > L->Last )
return ERROR;
else return i;
}
插入:先检查是否能插入,线性表是否已满
bool Insert( List L, ElementType X, Position P )
{
Position i;
if ( L->Last == MAXSIZE-1)
{
printf("线性表已满\n");
return false;
}
if ( P<0 || P>L->Last+1 )
{
printf("ERROR");
return false;
}
for( i=L->Last; i>=P; i-- )
L->Data[i+1] = L->Data[i];
L->Data[P] = X;
L->Last++;
return true;
}
删除:删除要看线性表是否为空,为空就出现错误了。
bool Delete( List L, Position P )
{
Position i;
if( P<0 || P>L->Last )
{
printf("ERROR\n");
return false;
}
for( i=P+1; i<=L->Last; i++ )
L->Data[i-1] = L->Data[i];
L->Last--;
return true;
}
线性表的链式存储结构实现
typedef struct LNode *PtrToLNode;
struct LNode {
ElementType Data;
PtrToLNode Next;
};
查找:
Position Find( List L, ElementType X )
{
Position p = L; /* p指向L的第1个结点 */
while ( p && p->Data!=X )
p = p->Next;
/* 下列语句可以用 return p; 替换 */
if ( p )
return p;
else
return ERROR;
}
插入:先构造一个新结点,再找到要插入位置i的前一个位置,这个结点指向新结点,然后新结点再指向下一个结点。
bool Insert( List L, ElementType X, Position P )
{ /* 这里默认L有头结点 */
Position tmp, pre;
/* 查找P的前一个结点 */
for ( pre=L; pre&&pre->Next!=P; pre=pre->Next ) ;
if ( pre==NULL ) { /* P所指的结点不在L中 */
printf("插入位置参数错误\n");
return false;
}
else { /* 找到了P的前一个结点pre */
/* 在P前插入新结点 */
tmp = (Position)malloc(sizeof(struct LNode)); /* 申请、填装结点 */
tmp->Data = X;
tmp->Next = P;
pre->Next = tmp;
return true;
}
}
删除:先找到链表的第i-1个结点,这个结点指向i+1个结点,就完成删除操作了。
bool Delete( List L, Position P )
{ /* 这里默认L有头结点 */
Position tmp, pre;
/* 查找P的前一个结点 */
for ( pre=L; pre&&pre->Next!=P; pre=pre->Next ) ;
if ( pre==NULL || P==NULL) { /* P所指的结点不在L中 */
printf("删除位置参数错误\n");
return false;
}
else { /* 找到了P的前一个结点pre */
/* 将P位置的结点删除 */
pre->Next = P->Next;
free(P);
return true;
}
}
广义表:就是比较复杂的链表。
Typedef struct GNode *GList;
struct GNode{
int Tag;
union{
ElmentType Data;
GList SubList;
}URegion;
GList Next;
};
多重链表:链表中的结点可能同时属于多个链,一个结点有多个指针域。
例:矩阵既可以用二维数组表示,但当数据比较稀疏时,会造成浪费,所以可以用十字链表来表示矩阵。每个结点有两个指针域,把同行同列的数据串起来,一个行指针(右指针)一个列指针(左指针)。用一个标识域来区分是否为头结点。
堆栈
简单计算机:一般我们使用中缀表达式表示,后缀表达式就可以用堆栈的方式算出来。
用两个栈来,一个栈来装运算数,一个栈来装运算符,当要装的运算符的优先级比栈顶的优先级更小时,全部出栈,用来运算,左括号放入运算符后,优先级变小。
堆栈:具有一定操作的线性表。操作有插入(入栈),删除(出栈),后入先出。
栈的顺序存储实现:
初始化:
typedef int Position;
struct SNode {
ElementType *Data; /* 存储元素的数组 */
Position Top; /* 栈顶指针 */
int MaxSize; /* 堆栈最大容量 */
};
typedef struct SNode *Stack;
创建:
Stack CreateStack( int MaxSize )
{
Stack S = (Stack)malloc(sizeof(struct SNode));
S->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
S->Top = -1;
S->MaxSize = MaxSize;
return S;
}
bool IsFull( Stack S )
{
return (S->Top == S->MaxSize-1);
}
push操作:如果栈满就出现错误
bool Push( Stack S, ElementType X )
{
if ( IsFull(S) ) {
printf("堆栈满");
return false;
}
else {
S->Data[++(S->Top)] = X;
return true;
}
}
pop操作:栈不能为空
bool IsEmpty( Stack S )
{
return (S->Top == -1);
}
ElementType Pop( Stack S )
{
if ( IsEmpty(S) ) {
printf("堆栈空");
return ERROR; /* ERROR是ElementType的特殊值,标志错误 */
}
else
return ( S->Data[(S->Top)--] );
}
栈的链式存储实现:
初始化:
typedef struct SNode *PtrToSNode;
struct SNode {
ElementType Data;
PtrToSNode Next;
};
typedef PtrToSNode Stack;
创建:
Stack CreateStack( )
{ /* 构建一个堆栈的头结点,返回该结点指针 */
Stack S;
S = (Stack)malloc(sizeof(struct SNode));
S->Next = NULL;
return S;
}
push操作:
bool IsEmpty ( Stack S )
{ /* 判断堆栈S是否为空,若是返回true;否则返回false */
return ( S->Next == NULL );
}
bool Push( Stack S, ElementType X )
{ /* 将元素X压入堆栈S */
PtrToSNode TmpCell;
TmpCell = (PtrToSNode)malloc(sizeof(struct SNode));
TmpCell->Data = X;
TmpCell->Next = S->Next;
S->Next = TmpCell;
return true;
}
pop操作:
ElementType Pop( Stack S )
{ /* 删除并返回堆栈S的栈顶元素 */
PtrToSNode FirstCell;
ElementType TopElem;
if( IsEmpty(S) ) {
printf("堆栈空");
return ERROR;
}
else {
FirstCell = S->Next;
TopElem = FirstCell->Data;
S->Next = FirstCell->Next;
free(FirstCell);
return TopElem;
}
}
队列
队列时具有一定操作约束的线性表,队列的特点是先进先出。队列的基本操作有:插入,删除。
队列的顺序存储实现:
初始化:
typedef int Position;
struct QNode {
ElementType *Data; /* 存储元素的数组 */
Position Front, Rear; /* 队列的头、尾指针 */
int MaxSize; /* 队列最大容量 */
};
typedef struct QNode *Queue;
创建:
Queue CreateQueue( int MaxSize )
{
Queue Q = (Queue)malloc(sizeof(struct QNode));
Q->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
Q->Front = Q->Rear = 0;
Q->MaxSize = MaxSize;
return Q;
}
插入:
bool IsFull( Queue Q )
{
return ((Q->Rear+1)%Q->MaxSize == Q->Front);
}
bool AddQ( Queue Q, ElementType X )
{
if ( IsFull(Q) ) {
printf("队列满");
return false;
}
else {
Q->Rear = (Q->Rear+1)%Q->MaxSize;
Q->Data[Q->Rear] = X;
return true;
}
}
删除:
ElementType DeleteQ( Queue Q )
{
if ( IsEmpty(Q) ) {
printf("队列空");
return ERROR;
}
else {
Q->Front =(Q->Front+1)%Q->MaxSize;
return Q->Data[Q->Front];
}
}
队列的链式存储实现:
初始化:
typedef struct Node *PtrToNode;
struct Node { /* 队列中的结点 */
ElementType Data;
PtrToNode Next;
};
typedef PtrToNode Position;
删除:
ElementType DeleteQ( Queue Q )
{
Position FrontCell;
ElementType FrontElem;
if ( IsEmpty(Q) ) {
printf("队列空");
return ERROR;
}
else {
FrontCell = Q->Front;
if ( Q->Front == Q->Rear ) /* 若队列只有一个元素 */
Q->Front = Q->Rear = NULL; /* 删除后队列置为空 */
else
Q->Front = Q->Front->Next;
FrontElem = FrontCell->Data;
free( FrontCell ); /* 释放被删除结点空间 */
return FrontElem;
}
}
多项式加法运算
算法思路:
两个指针指向两个多项式,当他们的指数相同时,系数相加,如果系数不为零,指向下一项。
#include<stdio.h>
#include<stdlib.h>
typedef struct PolyNode{
int coef;
int expon;
struct PolyNode *next;
} *Polynomial;
Polynomial InitPolynomial();
void TraverseList(Polynomial l);
void CreatePolynomial(Polynomial l);
Polynomial PolyAdd(Polynomial p1, Polynomial p2);
Polynomial attach(int coef, int expon, Polynomial p);//
void main()
{
Polynomial p1, p2, p;
p1 = InitPolynomial();
CreatePolynomial(p1);
p2 = InitPolynomial();
CreatePolynomial(p2);
//TraverseList(p1);
//TraverseList(p2);
p = PolyAdd(p1, p2);
p = p->next;
TraverseList(p);
}
Polynomial InitPolynomial()
{
Polynomial p;
p = (Polynomial)malloc(sizeof(PolyNode));
if (!p)
{
printf("fail");
exit(1);
}
p->next = NULL;
return p;
}
//遍历函数
void TraverseList(Polynomial l)
{
Polynomial r = l;
while (l)
{
printf("系数:%d,指数:%d ", l->coef, l->expon);
l = l->next;
}
printf("\n");
}
void CreatePolynomial(Polynomial l)
{
int i, n;
Polynomial p, r = l;
scanf_s("%d", &n);
scanf_s("%d,%d", &l->coef, &l->expon);
for (i = 1; i < n; i++)
{
p = (Polynomial)malloc(sizeof(PolyNode));
scanf_s("%d,%d", &p->coef, &p->expon);
r->next = p;
r = p;
}
r->next = NULL;
}
Polynomial PolyAdd(Polynomial p1, Polynomial p2)
{
int coef;
Polynomial r, p;
p = (Polynomial)malloc(sizeof(PolyNode));
p->next = NULL;
r = p;
while (p1 && p2)
{
if (p1->expon == p2->expon)
{
coef = p1->coef + p2->coef;
if (coef)
p = attach(coef, p1->expon, p);
p1 = p1->next;
p2 = p2->next;
}
else if (p1->expon > p2->expon)
{
p = attach(p1->coef, p1->expon, p);
p1 = p1->next;
}
else
{
p = attach(p2->coef, p2->expon, p);
p2 = p2->next;
}
}
for (; p1; p1 = p1->next) p = attach(p1->coef, p1->expon, p);
for (; p2; p2 = p2->next) p = attach(p2->coef, p2->expon, p);
return r;
}
Polynomial attach(int coef, int expon, Polynomial p)
{
Polynomial r;
r = (Polynomial)malloc(sizeof(PolyNode));
r->coef = coef;
r->expon = expon;
r->next = p->next;
p->next = r;
p = r;
return p;
}
一元多项式的加法与乘法运算
多项式表示有两种方式,一种数组,一种链表。用数组表示变成简单,容易操作。但用链表动态性更强。
用数组表示:
#include<stdio.h>
int main()
{
int n,m;
scanf("%d",&n);
int a[10001]={0},b[10001]={0},c[10001]={0},d[10001]={0};
int i,j;
for(i=0;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
a[y]=x;
}
scanf("%d",&m);
for(i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
b[y]=x;
}
for(i=0;i<=1000;i++)
{
for(j=0;j<=1000;j++)
c[i+j]+=a[i]*b[j];
}
int flag=0;
for(i=2000;i>=0;i--)
{
if(c[i]!=0)
{
if(flag)
printf(" ");
flag=1;
printf("%d %d",c[i],i);
}
}
if(!flag)
printf("0 0");
printf("\n");
for(i=0;i<=1000;i++)
{
for(j=0;j<=1000;j++)
d[i+j]=a[i]+b[i];
}
int mark=0;
for(i=1000;i>=0;i--)
{
if(d[i]!=0)
{
if(mark)
printf(" ");
mark=1;
printf("%d %d",d[i],i);
}
}
if(!mark)
printf("0 0");
printf("\n");
return 0;
}
用链表表示:
#include <stdio.h>
#include <stdlib.h>
typedef struct Polynode
{
int coef;
int exp;
struct Polynode *next;
}Polynode, *Polylist;
// 初始化
bool InitPoly(Polylist *Poly)
{
*Poly = (Polylist)malloc(sizeof(Polynode));
if (!(*Poly))
return false;
(*Poly)->next = NULL;
return true;
}
void PolyCreate(Polylist head, int n)
{
Polynode *rear, *s;
int c, e;
rear = head;
for (int i = 0; i < n; i++)
{
scanf("%d %d", &c, &e);
s = (Polynode*)malloc(sizeof(Polynode));
s->coef = c;
s->exp = e;
rear->next = s;
rear = s;
}
rear->next = NULL;
}
void Polyadd(Polylist polya, Polylist polyb)
{
Polynode *p, *q, *pre, *temp;
int sum;
p = polya->next;
q = polyb->next; /
pre = polya; // pre表示和多项式的尾节点,初始与polya相同
while (p != NULL && q != NULL)
{
if (p->exp > q->exp) // a的结点加入和多项式
{
pre->next = p; // p所指的结点加入和多项式
pre = p; // pre向后移动,尾插
p = p->next; // 扫描下一个p
}
else if (p->exp == q->exp) // 系数相等,对应系数相加
{
sum = p->coef + q->coef;
if (sum != 0)
{
p->coef = sum; // 修改p
pre->next = p; // 将p加入表尾
pre = p;
p = p->next; // p向后移动
temp = q;
q = q->next;
free(temp); // 释放系数相同的q结点
}
else
{
// 如果系数相同
temp = p;
p = p->next;
free(temp);
temp = q;
q = q->next;
free(temp);
}
}
else
{
pre->next = q;
pre = q;
q = q->next;
}
}
if (p != NULL)
pre->next = p;
else
pre->next = q;
}
// 插入
void Attach(int c, int e, Polylist* pRear)
{
Polynode *P;
P = (Polynode*)malloc(sizeof(Polynode));
P->coef = c;
P->exp = e;
P->next = NULL;
(*pRear)->next = P;
*pRear = P;
}
void clearPoly(Polylist poly)
{
Polynode* pTemp = poly;
while (poly)
{
pTemp = poly;
// 向后移动
poly = poly->next;
free(pTemp);
}
}
void PrintPoly(Polylist poly)
{
Polynode *p;
p = poly->next;
if (!p)
{
printf("0 0\n");
return;
}
printf("%d", p->coef);
printf(" %d", p->exp);
p = p->next;
while (p != NULL)
{
printf(" %d", p->coef);
printf(" %d", p->exp);
p = p->next;
}
printf("\n");
}
Polylist PolyMult(Polylist polya, Polylist polyb)
{
Polylist polyc;
Polynode *p, *q, *temp, *Rear;
int coef, exp;
InitPoly(&polyc);
Rear = polyc;
p = polya->next;
q = polyb->next;
if (!p||!q)
{
return polyc;
}
q = polyb->next;
while (q)
{
Polynode *P;
P = (Polynode*)malloc(sizeof(Polynode));
P->coef = p->coef*q->coef;
P->exp = p->exp+q->exp;
P->next = NULL;
Rear->next = P;
Rear = P;
q = q->next;
}
p = p->next;
// 将元素插入
while (p)
{
q = polyb->next;
Rear = polyc;
while (q)
{
exp = p->exp + q->exp;
coef = p->coef*q->coef;
while (Rear->next&&Rear->next->exp > exp)
{
Rear = Rear->next;
}
if (Rear->next&&Rear->next->exp == exp)
{
// 对应系数不为0
if (Rear->next->coef + coef)
{
Rear->next->coef += coef;
}
// 删去这个节点
else
{
temp = Rear->next;
Rear->next = temp->next;
free(temp);
}
}
// 如果这个指数不存在,添加这个节点到链表中
else
{
temp = (Polynode*)malloc(sizeof(Polynode));
temp->coef = coef;
temp->exp = exp;
temp->next = Rear->next;
Rear->next = temp;
Rear = Rear->next;
}
q = q->next;
}
p = p->next;
}
return polyc;
}
int main()
{
Polylist Polya, Polyb, Polyc;
int n, m;
InitPoly(&Polya);
InitPoly(&Polyb);
InitPoly(&Polyc);
scanf("%d", &n);
PolyCreate(Polya, n);
scanf("%d", &m);
PolyCreate(Polyb, m);
Polyc = PolyMult(Polya, Polyb);
PrintPoly(Polyc);
Polyadd(Polya, Polyb);
PrintPoly(Polya);
}