【数据结构 - 栈和队列】自学笔记记录(更新中……)

目录

一、栈

1、栈的定义及特点

2、顺序栈

1、顺序栈的存储结构

2、创建一个空顺序栈

3、顺序栈入栈

4、顺序栈出栈 ​

5、顺序栈取栈顶元素

6、清空一个顺序栈

7、销毁一个顺序栈

8、计算顺序栈中元素个数

9、实例分析——二进制转十进制

3、链栈

1、链栈的存储结构

2、创建一个空链栈 

3、链栈入栈 

4、链栈出栈

5、链栈取栈顶元素 

6、 计算链栈元素个数

7、销毁一个链栈 

二、队列 

1、队列的定义及特点

2、循环队列(队列的顺序表示)

1、循环队列的存储结构

2、构造一个空循环队列

3、求队列长度

4、循环队列入队

5、循环队列出队

6、循环队列取队头元素

3、链队(队列的链式表示)

 1、链队的存储结构

2、创建一个空链队

3、链队的入队

4、链队的出队

5、 取链队的队头元素

6、链队实例——舞伴问题

6-1 舞伴问题 (8 分)

4、栈与队列比较

5、课后习题


一、栈

1、栈的定义及特点

受特殊限制的线性表,先进后出后进先出

表尾端称为栈顶,表头端称为栈底,不含元素的空表称为空栈

栈的操作只在线性表表尾进行

top指向栈顶元素的后一位置

【数据结构 - 栈和队列】自学笔记记录(更新中……)_第1张图片

 

2、顺序栈

1、顺序栈的存储结构

#define MAXSIZE 100 		//顺序栈存储空间

typedef struct
{
    ElemType *base;     //栈底指针
	ElemType *top; 		//栈顶指针
	int stacksize; 			//栈当前可用的最大容量
}SqStack;

2、创建一个空顺序栈

Status InitStack( SqStack &S)
{
    S.base=(ElemType*)malloc(MAXSIZE*sizeof(ElemType));
    //S.base=new ElemType[MAXSIZE];
    if(!S.base) exit(OVERFLOW);
    S.top = S.base;  //一开始栈顶就是栈底
    S.stacksize = MAXSIZE;
    return OK;
}

3、顺序栈入栈

【数据结构 - 栈和队列】自学笔记记录(更新中……)_第2张图片

#define add 10 //追加空间

Status Push( SqStack &S, ElemType e)
{
    //如果栈满,追加空间
    if( S.top-S.base >= S.stacksize)
    {    
        S.base=(ElemType*)realloc(S.base,(s.stacksize + add)*sizeof(ElemType));
        if(!S.base) exit(OVERFLOW);
        
        S.top = S.base + S.stacksize;
        S.stacksize += add;
    }
    *(S.top ++) = e; //元素入栈,栈顶指针加一
}

4、顺序栈出栈 【数据结构 - 栈和队列】自学笔记记录(更新中……)_第3张图片

Status Pop( SqStack &S,ElemType &e)
{
    if(S.top == S.base) return ERROR; //空栈
    e =*(--S.top);  //栈顶指针减一,将栈顶元素赋值给e
    return OK;
}

5、顺序栈取栈顶元素

Status GetTop(SqStack S)
{
    if(S.top != S.base) 
        return *(S.top-1);  //返回栈顶元素,栈顶指针不变
}

6、清空一个顺序栈

清空栈不是把栈的存储空间销毁,而是把栈中元素作废

Status ClearStack(SqStack &S)
{
    S.top = S.base;
}

7、销毁一个顺序栈

Status DestroyStack( SqStack &S )
{
    int i,len;
    len = S.stacksize;
    for(i=0;i

8、计算顺序栈中元素个数

Status Stacklen( SqStack S )
{
    return (S.top - S.base);  //这里系统自动除以sizeof,所以返回的是元素个数
}

9、实例分析——二进制转十进制

#include 
#include 
#include 

//顺序栈定义
#define OK 1
#define ERROR 0
#define MAXSIZE  100    //顺序栈存储空间的初始分配量

typedef int Status;
typedef char ElemType;

typedef struct
{
	ElemType *base; //栈底指针
	ElemType *top;  //栈顶指针
	int stacksize;  //栈当前可用的最大容量
}SqStack;

//创建空栈
Status InitStack(SqStack *S)
{
	S->base=(ElemType*)malloc(MAXSIZE*sizeof(ElemType));
	if (!S->base) exit(0);
	S->top = S->base;
	S->stacksize = MAXSIZE;
	return OK;
}

//顺序栈的入栈
Status Push(SqStack *S, ElemType e)
{
	// 插入元素e为新的栈顶元素
	if (S->top - S->base == S->stacksize)  return ERROR; //栈满
	*(S->top ++) = e; //元素e压入栈顶,栈顶指针加1
	return OK;
}

//顺序栈的出栈
Status Pop(SqStack *S, ElemType *e)
{
	//删除S的栈顶元素,用e返回其值
	if (S->base == S->top) return ERROR;  //栈空
	*e = *(--S->top); //栈顶指针减1,将栈顶元素赋给e
	return OK;
}

//计算栈中元素个数
int Stacklen(SqStack S)
{
	return (S.top - S.base);
}

int main()
{
	SqStack s; //定义栈
    ElemType c;
    Status len,i,sum=0;

    InitStack(&s);

    printf("请输入二进制数,输入#符号表示结束!\n");
    scanf("%c",&c);
    while(c != '#')
    {
        Push(&s,c);
        scanf("%c",&c);
    }
    getchar(); //接收空格

    len = Stacklen(s);

    for( i=0; i

3、链栈

【数据结构 - 栈和队列】自学笔记记录(更新中……)_第4张图片

1、链栈的存储结构

typedef struct LNode
{
    ElemType data;
    struct LNode *next;
}LStackNode, *LinkStack;

2、创建一个空链栈 

void InitStack(LinkStack &Top)
{
    Top = (LinkStack)malloc(sizeof(LStackNode));
    if(!Top) return;
    Top->next = NULL;
}

3、链栈入栈 


void PushStack(LinkStack &Top, SElemType e)
{
    LinkStack newbase = (LinkStack)malloc(sizeof(LStackNode));
    if(!newbase)
    {
        printf("内存空间分配失败!\n");
        return;
    }
    newbase->data = e;
    newbase->next = Top->next;
    Top->next = newbase;
    return;
}

4、链栈出栈

void PopStack(LinkStack &Top, SElemType &e)
{
    LinkStack p = Top->next;
    if(!p)
    {
        printf("栈为空!\n");
        return;
    }
    Top->next = p->next;
    e = p->data;
    free(p);
    return;
}

5、链栈取栈顶元素 

void GetTopStack(LinkStack &Top, SElemType &e)
{
    LinkStack p = Top->next;
    if(!p)
    {
        printf("栈为空!\n");
        return;
    }
    e = p->data;
    return;
}

6、 计算链栈元素个数

int LengthStack(LinkStack &Top)
{
    int len=0;
    LinkStack p=Top;
    while(p->next!=NULL)
    {
        len++;
        p=p->next;
    }
    return len;
}

7、销毁一个链栈 

void FreeStack(LinkStack &Top)
{
    LinkStack p=Top,q;
    while(p->next!=NULL)
    {
        q = p;
        p = p->next;
        free(q);
    }
    printf("栈已销毁!\n");
    return;
}

 

二、队列 

1、队列的定义及特点

只允许在一端进行插入操作,而在另一端进行删除操作的线性表。

先进先出后进后出

【数据结构 - 栈和队列】自学笔记记录(更新中……)_第5张图片 

2、循环队列(队列的顺序表示)

【数据结构 - 栈和队列】自学笔记记录(更新中……)_第6张图片

 头指针head始终指向队列头元素,尾指针tail始终指向队尾元素的下一个位置

1、循环队列的存储结构

#define MAXSIZE 100  //最大队列长度

typedef struct
{
    ElemType *base; //类似顺序表中的elem数组
    int front;  //头指针,指向队列头元素
    int rear;   //尾指针,指向队列尾元素的下一个位置
}SqQueue;

2、构造一个空循环队列

Status InitQueue( SqQueue &Q )
{
    Q.base=(ElemType*)malloc(MAXSIZE*sizeof(ElemType));
    if(!Q.base) exit(OVERFLOW);
    Q.front = Q.rear = 0;
    return OK;
}

3、求队列长度

对于循环队列,头尾指针的差值可能是负数,因此要加上MAXSIZE,再与MAXSIZE取余

int Queuelength( SqQueue Q )
{
    return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;
}

4、循环队列入队

Status EnQueue( SqQueue &Q, ElemType e )
{
    if((Q.rear + 1) % MAXSIZE == Q.front)  return ERROR; //队满
                
    Q.base[Q.rear] = e; //队尾加新元素
    Q.rear = (Q.rear + 1)% MAXSIZE;
    return OK;
}

5、循环队列出队

Status DeQueue( SqQueue &Q, ElemType &e)
{
    if(Q.front = Q.rear)  return ERROR;  //队空
    e = Q.base[Q.front];    //保存表头元素
    Q.front = (Q.front+1) % MAXSIZE;
    return OK;
}

6、循环队列取队头元素

Status GetHead( SqQueue Q)
{
    if(Q.front != Q.rear)    //队非空
        return Q.base[Q.front];   //返回队头元素的值,队头指针不变
}

3、链队(队列的链式表示)

【数据结构 - 栈和队列】自学笔记记录(更新中……)_第7张图片

 1、链队的存储结构

typedef struct QNode
{
    ElemType data;
    struct QNode *next;
} QNode,*QueuePtr;

typedef struct
{
    QueuePtr front;    //队头指针
    QueuePtr rear;     //队尾指针
}LinkQueue;

2、创建一个空链队

Status InitQueue( LinkQueue &Q )
{
    Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
    //Q.front = Q.rear = new QNode;
    if(!Q.front) exit(OVERFLOW);
    Q.front->next = NULL;  //头指针置空
    return OK;
}

3、链队的入队

【数据结构 - 栈和队列】自学笔记记录(更新中……)_第8张图片

Status EnQueue(LinkQueue &Q, ElemType e)
{
    QueuePtr p=(QueuePtr)malloc(sizeof(QNode));
	if(!p) exit(OVERFLOW);
	p->data=e;
	p->next=NULL;
	Q.rear->next=p;  //尾指针指向的尾结点连接新结点
	Q.rear=p;  //尾指针指向新结点
}

4、链队的出队

【数据结构 - 栈和队列】自学笔记记录(更新中……)_第9张图片

Status DeQueue(LinkQueue &Q, ElemType &e)
{

	if(Q.front==Q.rear)//空队列
	    return ERROR;
	QueuePtr p = Q.front->next; //p指向首元结点
    e = p->data;
	Q.front->next=p->next;
	free(p);
	if(p==Q.rear)//此时删除最后一个结点(尾结点)
	    Q.rear = Q.front;
    return OK;
}

在链队出队操作时还要考虑当队列中最后一个元素被删后,队列尾指针也丢失了,

因此需对队尾指针重新赋值(指向头结点)

5、 取链队的队头元素

ElemType GetHead( LinkQueue Q )
{
    if(Q.front != Q.rear)  //队列非空
        return Q.front->next->data;  
}

6、链队实例——舞伴问题

6-1 舞伴问题 (8 分)

函数接口定义:

void DancePartner(DataType dancer[], int num) ;

其中 dancer[]是存放男士和女士信息的数组,num是数组大小。

裁判测试程序样例:

#include
#include

typedef struct {
    char name[20]; 
    char sex; 
} DataType;

struct Node {
    DataType      data;
    struct Node*  next;
};
typedef struct Node  *PNode;
struct Queue
{
    PNode        f;
    PNode        r;
};
typedef struct Queue *LinkQueue;
LinkQueue  SetNullQueue_Link()
{
    LinkQueue lqueue;
    lqueue = (LinkQueue)malloc(sizeof(struct Queue));
    if (lqueue != NULL)
    {
        lqueue->f = NULL;
        lqueue->r = NULL;
    }
    else
        printf("Alloc failure! \n");
    return  lqueue;
}

int IsNullQueue_link(LinkQueue lqueue)
{
    return (lqueue->f == NULL);
}

void EnQueue_link(LinkQueue lqueue, DataType x)
{
    PNode  p;
    p = (PNode)malloc(sizeof(struct Node));
    if (p == NULL)
        printf("Alloc failure!");
    else {
        p->data = x;
        p->next = NULL;
        if (lqueue->f == NULL)
        {
            lqueue->f = p;
            lqueue->r = p;
        }
        else
        {
            lqueue->r->next = p;
            lqueue->r = p;
        }
    }
}
void DeQueue_link(LinkQueue lqueue)
{
    struct Node  * p;
    if (lqueue->f == NULL)
        printf("It is empty queue!\n ");
    else
    {
        p = lqueue->f;
        lqueue->f = lqueue->f->next;
        free(p);
    }
}
DataType  FrontQueue_link(LinkQueue lqueue)
{
    if (lqueue->f == NULL)
    {
        printf("It is empty queue!\n");
    }
    else
        return (lqueue->f->data);
}

void DancePartner(DataType dancer[], int num) 
{
            /* 请在这里填写答案 */
}

int main()
{
    DataType dancer[9];
    for (int i = 0; i < 9; i++)
    scanf("%s %c", dancer[i].name, &dancer[i].sex);
    DancePartner(dancer, 9);
    return 0;
}

输入样例:

李敏浩 M
李钟硕 M
高欣雅 F
吴彦祖 M
王思聪 M
张甜源 F
张智霖 M
许丹丹 F
马小云 F

输出样例:

高欣雅 李敏浩
张甜源 李钟硕
许丹丹 吴彦祖
马小云 王思聪

张智霖

男女各一队,然后按队列顺序出队配对,最后输出没有配对的名字

void DancePartner(DataType dancer[], int num)
{
    LinkQueue fdancer = SetNullQueue_Link();
    LinkQueue mdancer = SetNullQueue_Link();
    
    for(int i=0;i

4、栈与队列比较

【数据结构 - 栈和队列】自学笔记记录(更新中……)_第10张图片

5、课后习题

1、设循环队列的元素存放在一维数组Q[0..29](下标为0到29)中,队列非空时,front指示队头元素位置,rear指示队尾元素的后一个位置。如果队列中元素的个数为11,front的值为25,则rear的值是( B

A.5

B.6

C.35

D.36

(Q.rear-Q.front+MAXSIZE)%MAXSIZE=队列长度

(x-25+30)%30 = 11 ,即x-25+30=11 ,则x=6.

2、将一个10×10对称矩阵M的上三角部分的元素mi,j(1≤i≤j≤10)按列优先存入C语言的一维数组N中,元素m7,2在N中下标是( C

A.15

B.16

C.22

D.23

【数据结构 - 栈和队列】自学笔记记录(更新中……)_第11张图片

 因为对称矩阵,所以m7,2跟m2,7一样,因为列优先,则第一列1个,第二列2个……第七列2个

1+2+3+4+5+6+2=23,由于数组从0开始,则位置应是22

3、对n阶对称矩阵压缩存储时,需要表长为( C )的顺序表

A.n/2

B.n*n/2

C.n(n+1)/2

D.n(n-1)/2

对称矩阵的存储只需要存储其上三角或下三角部分(含对角线),元素个数为n +(n-1)+ (n -2) +..*+ 1 =n(n+1)/2

你可能感兴趣的:(数据结构笔记,数据结构,c#)