浙大2020年Mooc数据结构笔记--第二讲线性结构

浙大2020年Mooc数据结构笔记–第二讲线性结构

〇、前言

  • 这几天开始跟着学数据结构,鉴于当初数据结构实在学的太弱,加之这项工作算是为大家之后复习、机试铺路。确实是一个迫切需要做的大规模工作。行胜于言,虽然从第二篇开始,坚持下去。

这眉毛和我很像

  • 此文部分为自己写,部分参考网上内容。提前说一下哈。期待批评指正。

一、线性表

线性表(Linear List):由同类型数据元素构成有序序列的线性结构
线性表的相关操作:
List MakeEmpty():初始化一个空线性表L;
ElementType FindKth( int K, List L ):根据位序K,返回相应元素 ;
int Find( ElementType X, List L ):在线性表L中查找X的第一次出现位置;
void Insert( ElementType X, int i, List L):在位序i前插入一个新元素X;
void Delete( int i, List L ):删除指定位序i的元素;
int Length( List L ):返回线性表L的长度n。

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

typedef int Position;
typedef struct LNode *List;
struct LNode {
    ElementType Data[MAXSIZE];
    Position Last;
};
 
/* 初始化 */
List MakeEmpty()
{
    List L;
 
    L = (List)malloc(sizeof(struct LNode));
    L->Last = -1;
 
    return L;
}
 
/* 查找 */
#define ERROR -1
 
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;  /* 找到后返回的是存储位置 */
}
 
/* 插入 */
/*注意:在插入位置参数P上与课程视频有所不同,
课程视频中i是序列位序(从1开始),这里P是存储下标位置(从0开始),两者差1*/
bool Insert( List L, ElementType X, Position P ) 
{ /* 在L的指定位置P前插入一个新元素X */
    Position i;
 
    if ( L->Last == MAXSIZE-1) {
        /* 表空间已满,不能插入 */
        printf("表满"); 
        return false; 
    }  
    if ( P<0 || P>L->Last+1 ) { /* 检查插入位置的合法性 */
        printf("位置不合法");
        return false; 
    } 
    for( i=L->Last; i>=P; i-- )
        L->Data[i+1] = L->Data[i]; /* 将位置P及以后的元素顺序向后移动 */
    L->Data[P] = X;  /* 新元素插入 */
    L->Last++;       /* Last仍指向最后元素 */
    return true; 
} 
 
/* 删除 */
/*注意:在删除位置参数P上与课程视频有所不同,
课程视频中i是序列位序(从1开始),这里P是存储下标位置(从0开始),两者差1*/
bool Delete( List L, Position P )
{ /* 从L中删除指定位置P的元素 */
    Position i;
 
    if( P<0 || P>L->Last ) { /* 检查空表及删除位置的合法性 */
        printf("位置%d不存在元素", P ); 
        return false; 
    }
    for( i=P+1; i<=L->Last; i++ )
        L->Data[i-1] = L->Data[i]; /* 将位置P+1及以后的元素顺序向前移动 */
    L->Last--; /* Last仍指向最后元素 */
    return true;   
}

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

在这里插入图片描述

typedef struct LNode *PtrToLNode;
struct LNode {
    ElementType Data;
    PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;
 
/* 查找 */
#define ERROR NULL
 
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;
}
 
/* 带头结点的插入 */
/*注意:在插入位置参数P上与课程视频有所不同,
课程视频中i是序列位序(从1开始),这里P是链表结点指针,在P之前插入新结点 */
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;
    }
}
 
/* 带头结点的删除 */
/*注意:在删除位置参数P上与课程视频有所不同,
课程视频中i是序列位序(从1开始),这里P是拟删除结点指针 */
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;
    }
}

二、堆栈

  1. 堆栈是一个特殊的线性结构
  2. “后入先出”的特点,只能在一端做插入,删除
  3. 堆栈相关操作:
    Stack CreateStack(int MaxSize ):初始化空堆栈;
    int isFull(Stack S,int MaxSize ):判断堆栈S是否已满;
    void Push(Stack S,ElementType item):将元素item压入堆栈;
    int IsEmpty(Stack S ): 判断堆栈S是否为空;
    ElementType Pop(Stack S):删除并返回栈顶元素
    在这里插入图片描述

1、堆栈的定义与操作,顺序存储实现

#include<iostream>
using namespace std;

typedef int Position;
struct SNode{
	ElementType *Data;	//存储元素数组 
	Position Top;		//栈顶指针 
	int MaxSize;		// 堆栈的最大容量 
};

typedef struct SNode *Stack;

//初始化 
Stack CreateStack(int MaxSize){
	Stack S = (Stack)malloc(sizeof(struck 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);
 } 
 
//入栈
bool Push( Stack S,ElementType X){
	if(isFull(S)){
		printf("堆栈满");
		return false; 
	}else{
		S->Top++;
		S->Data[S->Top] = X;
		return true;
	}
}

//是否为空 
bool isEmpty(Stack S){
	return (S->Top == -1);
} 

//入栈
ElementType Pop(Stack S){
	if(isEmpty(S)){
		printf("堆栈空");
		return ERROR; 
	}else {
		return (S->Data[(S->Top)--]);
	}
} 

2、堆栈的定义与操作,链式存储实现

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

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

//将元素压入堆栈S 
bool Push(Stack S,ElementType X){
	PtrToSNode TmpCell;
	TmpCell = (PtrToSNode)malloc(sizeof(struct SNode));
	TmpCell ->Data = X;
	TmpCell ->Next = S ->Next;
	S->Next = TmpCell;
	return true; 
}

//使栈顶元素出栈 
ElementType Pop(Stack 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;
	}
}

三、队列

  1. 队列的特点为“先进先出”;
  2. 队列的相关操作:
    Queue CreatQueue( int MaxSize ):生成长度为MaxSize的空队列;
    int IsFullQ( Queue Q, int MaxSize ):判断队列Q是否已满;
    void AddQ( Queue Q, ElementType item ):将数据item插入队列Q中;
    int IsEmptyQ( Queue Q ): 判断队列Q是否为空;
    ElementType DeleteQ( Queue Q ):将队头数据从队列中删除并返回。
    在这里插入图片描述

1、队列的定义与操作,顺序存储实现

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 ERROR; 
	}else{
		Q->Rear = (Q->Rear +1)%Q->MaxSize;
		Q->Data[Q->Rear] = X;	
	}
}

bool IsEmpty(Queue Q){
	return (Q->Front == Q->Rear);
}

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

2、队列的定义与操作,链式存储实现

typedef struct Node *PtrToNode;
struct Node { /* 队列中的结点 */
    ElementType Data;
    PtrToNode Next;
};
typedef PtrToNode Position;
 
struct QNode {
    Position Front, Rear;  /* 队列的头、尾指针 */
    int MaxSize;           /* 队列最大容量 */
};
typedef struct QNode *Queue;
 
bool IsEmpty( Queue Q )
{
    return ( Q->Front == NULL);
}
 
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;
    }
}

四、一元多项式的加法与乘法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
具体代码实现在实验题第二题

五、课后题

在这里插入图片描述

1、02-线性结构1 两个有序链表序列的合并 (15分)

在这里插入图片描述

#include<stdlib.h>
#include<iostream>
using namespace std; 
 
typedef struct node *ptrNode;
typedef ptrNode LinkList;  //头结点
typedef ptrNode Position;//中间节点
typedef int ElementType;
struct node{
	ElementType Element;
	Position next;
};
 
int IsEmpty(LinkList L)
{
	return L->next == NULL;
}
 
LinkList creatList(void)              
{
	LinkList head,r,p;
	int x;
	head = (struct node*)malloc(sizeof(struct node));    //生成新结点
	r = head;
	scanf("%d",&x);
 
	while(x != -1){
		p = (struct node*)malloc(sizeof(struct node));
		p->Element = x;
		r->next = p;
		r = p;
		scanf("%d",&x);
	}
	r->next = NULL;
	return head;
}
 
LinkList mergeList(LinkList a, LinkList b)
{
	Position ha, hb,hc;
	LinkList c,r,p;
 
	ha = a->next;
	hb = b->next;
	
	c = (struct node*)malloc(sizeof(struct node));
	r = c;
	while((ha != NULL)&&(hb != NULL)){
		p = (struct node*)malloc(sizeof(struct node));
		if(ha->Element <= hb->Element){
			p->Element = ha->Element;
			ha = ha->next;
		}
		else{
			p->Element = hb->Element;
			hb = hb->next;
		}
 
		r->next = p;
		r = p;
	}
	if(ha == NULL){
		while(hb != NULL){
			p = (struct node*)malloc(sizeof(struct node));
			p->Element = hb->Element;
			hb = hb->next;
			r->next = p;
		    r = p;
		}
	}
	if(hb == NULL){
		while(ha != NULL){
			p = (struct node*)malloc(sizeof(struct node));
			p->Element = ha->Element;
			ha = ha->next;
			r->next = p;
		    r = p;
		}
	}
 
	r->next = NULL;
 
	return c;
}
 
void printList(LinkList L)
{
	LinkList hc;
	int flag = 0;
 
	hc = L->next;
	if(hc == NULL)
		printf("NULL");
	while(hc != NULL){
		if(flag)
			printf(" ");
		else
			flag = 1;
		printf("%d",hc->Element);
		hc = hc->next;
	}
}
 
int main(void)
{
	LinkList L1,L2,L3;
	L1 = creatList();
	L2 = creatList();
	L3 = mergeList(L1,L2);
	printList(L3);
	return 0;
}
 

输入测试:
1 2 3 -1
4 5 9 -1
输出结果:
1 2 3 4 5 9

02-线性结构2 一元多项式的乘法与加法运算(20分)

#include<stdio.h>
#include<stdlib.h>

typedef struct PolyNode *Polynomial;	//多项式链指针 
struct PolyNode{
	int coef;	//系数 
	int expon;	//指数 
	Polynomial link;	//链指针 
};

//将某项链接到结果上 
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;
}

//读取多项式 
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;
}


//多项式相加过程 
Polynomial Mult(Polynomial P1, Polynomial P2){
  	Polynomial t1,t2,P,Rear,t;
  	int e,c;
	if(!P1||!P2) return NULL;		//如果两个多项式有空,则返回NULL 
  	t1 = P1; t2 = P2;		
  	P = (Polynomial)malloc(sizeof(struct PolyNode));
    P->link = NULL;					//创建结果多项式,最后要返回的值	
									//t1指向P1,t2指向P2,Rear指向P 
	Rear=P;
    while(t2){
	    Attach(t1->coef*t2->coef,t1->expon+t2->expon,&Rear);
	    t2 = t2->link;
  	}
  	t1 = t1->link;
  	while(t1){
    	Rear = P;
    	t2 = P2;
    	while(t2){
	      	c = t1->coef*t2->coef;
	      	e = t1->expon+t2->expon;
	      	while(Rear->link&&Rear->link->expon>e) 
			  	Rear=Rear->link;
	      	if(Rear->link &&Rear->link->expon==e){
	        	if(Rear->link->coef+c) 
					Rear->link->coef+=c;
	        	else{
	          		t = Rear->link;
	          		Rear->link = t->link;
	          		free(t);
	        	}
	      	}
	      	else{
	        	t = (Polynomial)malloc(sizeof(struct PolyNode));
	        	t->coef = c;
	        	t->expon=e;
	        	t->link = Rear->link;
	        	Rear->link =t;
	        	Rear = Rear->link;
	      	}
	      	t2 = t2->link;
    	}
    	t1 = t1->link;
  	}
  	t = P; P = P->link; free(t);
  	return P;
}

Polynomial Add(Polynomial P1, Polynomial P2){
  	Polynomial t1,t2,P,Rear,t;
  	int e,c;
  	if(!P1&&!P2) return NULL;
  	t1 = P1;
  	t2 = P2;
  	P=(Polynomial)malloc(sizeof(struct PolyNode));
  	Rear = P;
  	while(t1&&t2){
    	if(t1->expon==t2->expon){
      		if(t1->coef!=-(t2->coef)) 
			  	Attach(t1->coef+t2->coef, t1->expon, &Rear);
      		t1 = t1->link;
      		t2 = t2->link;
    	}
    	else if(t1->expon>t2->expon){
      		Attach(t1->coef, t1->expon, &Rear);
      		t1 = t1->link;
    	}
    	else {
      		Attach(t2->coef, t2->expon, &Rear);
      		t2 = t2->link;
    	}
  	}
  	Rear->link = t1 ? t1 : t2;
  	t = P; P = P->link; free(t);
  	return 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;
	}
	printf("\n");
}

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

输入样例:

4 3 4 -5 2 6 1 -2 0
3 5 20 -7 4 3 1

输出样例:

15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
5 20 -4 4 -5 2 9 1 -2 0

3、02-线性结构3 Reversing Linked List (25分) 在这里插入图片描述

Sample Input:

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

Sample Output:

00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1

这题开始都看不懂题意,后来看懂,根据对比输入样例贺输出样例,灵感乍现。第一行的00100 是链表第一个元素的位置,6的意思是共有6个元素,4的意思是每4个节点反转一次。下面的6行,例如第一行:00000的位置存放的是4,4的下一个节点位置在12309.之后同理。输出也是一样的。通过开辟大规模数组即可解决问题。

#include <stdio.h>
#include <stdlib.h>
#define MaxSize 100005
int main(){
	int Data[MaxSize];		// 存放数据 
	int Next[MaxSize];		//存放相邻关系 
	int List[MaxSize];
	int FirstAdd,N,K;
	scanf("%d %d %d",&FirstAdd,&N,&K);
	int i,j;
	for(i=0;i<N;i++){
		int tAdd,tData,tNext;
		scanf("%d %d %d",&tAdd,&tData,&tNext);
		Data[tAdd]=tData;
		Next[tAdd]=tNext;
	}
	int sum=0;
	while(FirstAdd!=-1){
		List[sum++]=FirstAdd;   
		FirstAdd=Next[FirstAdd];		//此时List里面按顺序存放着反转前的各数字位置 
	}
	for(i=0;i<sum-sum%K;i+=K){
		for(j=0;j<K/2;j++){
			int t=List[i+j];			//对List内的位置进行反转即可 
			List[i+j]=List[i+K-j-1];
			List[i+K-j-1]=t;
		}
	}
	for(i=0;i<sum-1;i++){
		printf("%05d %d %05d\n",List[i],Data[List[i]],List[i+1]);
	}
	printf("%05d %d -1\n",List[i],Data[List[sum-1]]);
	return 0;
}

4、02-线性结构4 Pop Sequence (25分)

在这里插入图片描述

Sample Input:

5 7 5
1 2 3 4 5 6 7
3 2 1 7 5 6 4
7 6 5 4 3 2 1
5 6 4 3 7 2 1
1 7 6 5 4 3 2

Sample Output:

YES
NO
NO
YES
NO

#include <stdio.h>
#include <stdlib.h>
typedef struct SNode *Stack;
struct SNode{
	int data[1010];
	int top;
};
void push(Stack ptrl,int a);
void pop(Stack ptrl);
int main(){
	Stack ptrl;
	ptrl=(Stack)malloc(sizeof(struct SNode));
//	ptrl->top=-1;
	int m,n,k,i,j;
	scanf("%d %d %d",&m,&n,&k);
	int b[1010];
	while(k--){
		ptrl->top=-1;
		j=0;
		for(i=0;i<n;i++){
			scanf("%d",&b[i]);
		}
		for(i=1;i<=n;i++){
			push(ptrl,i);
			if(ptrl->top >= m){
				break;
			}
			while(ptrl->top!=-1&&ptrl->data[ptrl->top]==b[j]){
				j++;
				pop(ptrl);
			}
		}
		if (ptrl->top == -1) {
			printf("YES\n");
		}
		else {
			printf("NO\n");
		}
	}
}
void push(Stack ptrl,int a){
	ptrl->data[++(ptrl->top)]=a;
}
void pop(Stack ptrl){
	ptrl->top--;
}

总结

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值