C语言-数据结构(二)

单链表(二)

6、单链表的建立
尾插法

LinkList List_TailInsert(LinkList *L){
    int x;
    L = (LinkList) malloc(sizeof (LNode)); //建立一个头结点
    LNode *s, *r = L; //r为指向表尾结点的指针
    scanf("%d", &x);
    while(x != 9999){ //取一个特殊值表示输入结束
        s=(LNode *) malloc(sizeof (LNode));
        s->data = x;
        r->next = s; //在r结点之后插入元素x
        r = s;
        scanf("%d", &x);
    }
    r->next = NULL; //最后的尾结点置空
    return L;
}

头插法

LinkList List_HeadInsert(LinkList L){ //逆向建立单链表
    LNode *s;
    int x;
    L = (LinkList) malloc(sizeof (LNode)); //建立一个头结点
    L->next = NULL; //初始化为空链表
    scanf("%d", &x);
    while(x != 9999){ //取一个特殊值表示输入结束
        s=(LNode *) malloc(sizeof (LNode));
        s->data = x;
        s->next = L->next;
        L->next = s; //将新结点插入表中,L为头指针
        scanf("%d", &x);
    }
    return L;
}

二、双链表

1、建立双连表

typedef struct DNode{
    int data;
    struct DNode *prior, *next;
}DNode, *DLinklist;

bool InitDLinklist(DLinklist L){
    L = (DNode *) malloc (sizeof (DNode)); //分配一个头结点
    if(L == NULL) //内存不足,分配失败
        return false;
    L->prior = NULL; //头结点的prior永远指向NULL
    L->next = NULL; //头结点之后暂时还有结点
    return true;
}

bool Empty(DLinklist L){ //带头结点的双链表判断是否为空
    if(L->next == NULL)
        return true;
    else
        return false;
}

2、双链表的插入

bool InsertNextDNode(DNode *p, DNode *s){
    if(p == NULL || s==NULL)
        return false;
    s->next = p->next;
    if(p->next != NULL) //如果p结点有后继结点
        p->next->prior = s;
    s->prior = p;
    p->next = s;
}

3、双链表的删除

bool DeleteNextDNode(DNode *p){
    if(p==NULL)
        return false;
    DNode *q = p->next; //找到p的后继结点q
    if(q==NULL)
        return false; //p没有后继
    p->next = q->next;
    if(q->next != NULL) //趴结点不是最后一个结点
        q->next->prior = p;
    free(q); //释放结点空间
    return true;
}

4、销毁一个双链表

void DestoryList(DLinklist L){
    while (L->next != NULL)
        DeleteNextDNode(L);
    free(L); //释放头结点
    L=NULL; //头指针指向NULL
}

三、循环链表

1、循环单链表

typedef struct LNode{
    int data;
    struct LNode *next;
}LNode, *LinkList;

bool InitList(LinkList L){ //初始化一个循环单链表
    L = (LNode *) malloc(sizeof (LNode)); //分配一个头结点
    if(L==NULL)
        return false;
    L->next = L; //头结点next指向有结点
    return true;
}

bool Empty(LinkList L){
    if(L->next == L)
        return true;
    else
        return false;
    
}

bool isTail(LinkList L, LNode *p){ //判断结点p是否为循环单链表的表尾结点
    if(p->next==L)
        return true;
    else
        return false;
}

2、循环双链表

typedef struct DNode{
    int data;
    struct DNode *prior, *next;
}DNode, *DLinklist;

bool InitDLinkList(DLinklist L){
    L = (DNode *) malloc(sizeof (DNode));
    if(L==NULL)
        return false;
    L->prior = L;
    L->next = L;
    return true;
}

bool Empty(DLinklist L){
    if(L->next == L)
        return true;
    else
        return false;
}

bool isTail(DLinklist L, DNode *p){
    if(p->next == L)
        return true;
    else
        return false;
}

四、静态链表

1、定义一个静态链表
两种方式:

#define MaxSize 10 //静态链表的最大长度
struct Node{ //静态链表结果类型的定义
    int data; //存储数据元素
    int next; //下一个元素的数值下标
};
typedef struct Node SLinkList[MaxSize];
typedef struct {
    int data;
    int next;
}SLinkList[MaxSize];

2、静态链表的优缺点
优点:增、删操作不需要大量移动元素
缺点:不能随机存取,只能从头结点开始依次往后查找;容量固定不变

五、栈

1、定义顺序栈

#define MaxSize 10 //定义栈中元素的最大个数
typedef struct{
    int data[MaxSize];  //静态数组存放栈中元素
    int top; //栈顶指针
}SqSrack;

2、栈的初始化

void InitStack(SqStack *S){
    S->top = -1; //初始化栈顶指针
    //S->top = 0; 第二种初始化方式,此时top指向的是下一个可以放元素的位置
}

3、栈的判空操作

bool StackEmpty(SqStack S){ //判断栈空
    if(S.top == -1) //第二种方式判空条件:S.top == 0
        return true;
    else
        return false;
}

4、新元素入栈

bool Push(SqStack *S, int x){
    if(S->top == MaxSize-1) //栈满,报错
        return false;
    S->top = S->top + 1; //指针先加1
    S->data[S->top] = x; //新元素入栈
    //    S->data[++S->top = x; 可替换上两行
    //    S->data[S.top++] = x; 第二种方式的进栈操作
    return true; 
}

5、出栈操作

bool Pop(SqStack *S, int x){ //出找操作
    if(S->top == -1)
        return false;
    x = S->data[S->top]; //栈顶元素先出栈
    S->top = S->top - 1; //指针再减1
    //    x = S->data[S->top--]; 可替换上两行
    //    x = S->data[--S->top]; 第二种方式的出栈操作
    return true;
}

6、取栈顶元素

bool GetTop(SqStack S, int x){ //取栈顶元素
    if(S.top == -1)
        return false;
    x = S.data[S.top]; //x记录栈顶元素
    return true;
}

7、顺序栈的缺点:栈的大小不可变
8、共享栈:指两个栈共享一片内存空间
初始化共享栈:

#define MaxSize 10
typedef struct{
    int data[MaxSize];
    int top0; //0号栈栈顶指针
    int top1; //1号栈栈顶指针
}ShStack;

初始化栈顶指针:

void InitShStack(ShStack *S){
    S->top0 = -1;
    S->top1 = MaxSize;
}

共享栈栈满条件:top0 + 1 == top1
9、链栈
链栈一般不带头结点:

typedef struct StackNode{ //定义一个不带头结点的链表栈
    int data;
    struct StackNode *next;
}SNode, *StackList;

typedef struct{
	StackList top;
	int count;
}LinkStack;

bool InitStackNode(StackList *S){ //初始化一个链表栈
    S = NULL;
    return true;
}

bool Empty(StackList S){ //判断一个链表栈是否为空
    return (S == NULL);
}

入栈(头插法):

bool StackPush(LinkStack *S, int e){
    StackList s = (StackList) malloc (sizeof (StackNode));
    s->data = e; 
    s->next = S->top; //把当前栈顶指针赋给新结点的后继
    S->top = s; //将新结点置为栈顶指针
    S->count++;
    return true;
}

出栈(删除第一个结点):

bool StackPop(StackList *S, int *e){ 
    StackList p;
    if(StackEmpty(*S))
    	return false;
   	*e = S->top->data; //保存当前栈顶元素的值
   	p = S->top; //将当前栈顶指针指向的结点赋值给p
   	S->top = S->top->next; //将栈顶指针向下移一位
   	free(p); //释放结点p
   	S->count--;
   	return true;
}

10、队列
定义一个队列:

#define MaxSize 10
typedef struct {
    int data[MaxSize]; //用静态数组存放队列元素
    int front, rear; //队头指针和队尾指针
}SqQueue;
void InitQueue(SqQueue *Q){ //初始化队列
    Q->rear = Q->front = 0; //初始时,队头、队尾指针指向0
}
bool QueueEmpty(SqQueue Q){ //判断队列是否为空
    if(Q.rear == Q.front) //队空条件
        return true;
    else
        return false;
}
bool EnQueue(SqQueue *Q, int x){ //入队
    if((Q->rear+1)%MaxSize == Q->front) //判断队列满的条件
        return false;
    Q->data[Q->rear] = x; //新元素插入队尾
    Q->rear = (Q->rear+1)%MaxSize; //队尾指针向后移一位,若到最后一个元素,则转到第一个元素位置
    return true; 
}
bool DeQueue(SqQueue *Q, int x){ //出队
    if(Q->rear == Q->front) //判断队空
        return false;
    x = Q->data[Q->front]; //将队头元素赋值给e
    Q->front = (Q->front+1)%MaxSize; //队头指针向后移一位,如果到最后一位则转到第一个元素位置
    return true;
}
bool GetHead(SqQueue Q, int x){ //返回队头元素的值,用x返回
    if(Q.rear == Q.front)
        return false;
    x = Q.data[Q.front]; 
    return true;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值