2020年考研数据结构复习——单链表

2020年考研数据结构复习——单链表

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include "malloc.h"

//单链表存储结构
typedef struct LNode
{
    int data;
    struct LNode *next;

} LNode, *LinkList;

//头插法
void CreateList_L(LinkList &L)
{
    //头插法建立带头节点的链表
    L->next = NULL;//先建立一个带头节点的单链表
    int x;
    scanf("%d", &x); //输入元素值
    while(x!=-1)
    {
        LNode *p = (LNode*)malloc(sizeof(LNode));
        p -> data = x;
        p -> next = L->next;
        L->next = p; //插入
        scanf("%d", &x);
    }
}


void CreateList_L2(LinkList &L)
{
    //尾插法建立带头节点的链表
    L->next = NULL;//先建立一个带头节点的单链表
    LNode *q = L;
    int x;
    scanf("%d", &x); //输入元素值
    while(x!=-1)
    {
        LNode *p = (LNode*)malloc(sizeof(LNode));
        p -> data = x;
        p -> next = NULL;
        q -> next = p;
        q = p; //q用于保存最后一个链表节点
        scanf("%d", &x);
    }
}

//计算链表的长度
int Link_length(LinkList L)
{
    //计算链表的长度
    LNode *p = L->next;
    int length = 0;
    while(p!=NULL)
    {
        length++;
        p = p->next;
    }
    return length;
}

//取得第i项的值,按位置查找
int GetElem(int i, LinkList L)
{
    if(i<0&&i>Link_length(L))
        return -1;//查询位置不合法,返回-1
    LNode *p = L->next;
    int l = 1;
    while(p!=NULL)
    {
        if(l==i)
            return p->data;
        p = p->next;
        l++;
    }

}
//返回最后一个LNode节点
LNode* lastlnode(LinkList L)
{

    LNode *p = L;
    while(p->next!=NULL)
    {
        p = p->next;
    }
    return p;
}

//头插法
void insert_head(LinkList &L, int x)
{
    LNode *p = (LNode*)malloc(sizeof(LNode));
    if (p==NULL)
        return;
    p->data = x;
    p->next = L->next;//新建节点指向头节点的下一个
    L->next = p; //p指向头节点后,即将新节点插入链表中
}

//尾插法
void insert_tail(LinkList &L, int x)
{
    LNode *p = (LNode*)malloc(sizeof(LNode));
    if (p==NULL)
        return;
    p->data = x;
    p->next = NULL;
    LNode *q = lastlnode(L);
    q->next = p; //将新节点插入链表中
}

//删除指定位置的节点,并返回其值
void delete_head(int i,int &x,LinkList &L)
{
    if(i<0&&i>Link_length(L))
        return;//删除位置不合法,返回-1
    LNode *p = L;
    LNode *q = L;

    int l = 0;
    while(p!=NULL)
    {
        q = p->next;
        if(l+1==i)
            p->next=q->next;
        x=p->data;
        free(q);
        char str[10]="删除成功";
        printf("%s\n",str);
        return;
        p = p->next;
        l++;
    }
}

//转置
void reserve(LinkList &L)
{
    if(L==NULL||L->next==NULL||L->next->next==NULL)
        return;
    LNode *p = L->next;
    LNode *q = p->next;
    p->next = NULL; //第一个p相当于最后一个,其指针域指向空
    LNode *l;
    while(q->next != NULL)
    {
        l = q->next;
        q->next = p;
        p = q;
        q = l;
    }
    //q->next == NULL 即q是最后一个结点
    q->next = p;
    L->next = q; //头结点指向原来的最后一个
}

//单链表的升序排序(采用冒泡排序)
void sort_list(LinkList L)
{
    if(L==NULL||L->next->next==NULL)
        return;

    LNode *p,*q,*temp,*l,*tail;
    p = L;
    q = p->next;
    tail = NULL;
    while(L->next!=tail)
    {
        p = L;
        q = p->next;
        while(q->next!=tail)
        {
            l = q->next;
            if(l->data < q->data) //逆序
            {
                q->next=l->next;
                l->next=q;
                p->next=l;
                temp=l;
                l=q;
                q=temp;
            }
            p=q;
            q=l;
        }
        tail=q;//q->next==NULL,则q是最后一个
    }

}

//打印
void print(LinkList L)
{
    LinkList p = L;
    while(p!=NULL)
    {
        p= p->next;
        printf("%d\n",(p->data));
    }
}

int main()
{
    LinkList L = NULL; //这里表示的已经是已经个指针了
    L = (LinkList )malloc(sizeof(LNode));
    if(L==NULL)
    {
        return -1;
    }
    CreateList_L(L); //头插法建立单链表
    //CreateList_L2(L); //尾插法建立单链表
    //printf("%d\n",Link_length(L)); //测试,输出链表长度
    //printf("%d\n",GetElem(2,L)); //取得第二项元素对应的值
    //insert_head(L,4);
    //insert_tail(L,5);
    //int x;
    //delete_head(1,x,L);//测试删除是否成功
    //reserve(L);//倒置的测试
    //sort_list(L);//排序测试
    print(L);
}

//还要写单链表的排序

//逆置单链表

知识点

结构体的别名问题:

Node定义了一个Node型的节点对象,

PNode定义了一个指向Node型节点对象的Node型指针;

给这个指向node结构体指针类型的node定义了一个别名,

任何使用node*的地方都可以直接用PNode代替。

因使用时可能会忘记该别名是指针类型的,易犯错,不建议使用。

其他链表

循环链表

与单链表的区别仅在于,判别链表中最后一个结点的条件由“后继是否为空”变为“后继是否为头结点”

特点:

(1)对于单链表仅能从头结点开始遍历整个链表,而对于单循环链表则可以从表中任意结点开始遍历整个链表。

(2)有时对链表常做的操作是在表头、表尾进行,此时可以使用表尾标识链表,操作效率会提高。

双向链表

除了存在一个指向后继的指针域外,还存在一个指向前驱的指针域

操作特点

(1)“查询”和单链表相同

(2)“插入”和“删除”时需要同时修改两个方向上的指针;

插入:

newnode -> next = p -> next;
newnode -> prior = q->prior;
p -> next = newnode;
q -> prior = newnode;

删除:

p -> next = node -> next;
q -> prior = node -> prior;
free(node);

特点

(1) 从某个结点出发到其直接前驱结点或直接后继结点,时间复杂度均为O(1);

(2) 查找第i个结点、向第i个结点插入 或 删除第i个结点,都要区分是哪个方向;

(3) 如果是双向循环链表,修改指针要同时考虑在前驱结点和后继结点上的修改;

(4) 某个结点的直接前驱的直接后继,或它的直接后继的直接前驱,即为该结点本身。

静态链表
与借助数组来描述线性表的链式存储结构不同,静态链表结点也有数据域data和指针域next,

但是与前面所讲的链表中的指针有所不同的是,这里的指针是结点的相对地址(即数组的下标),称之为静态指针。
静态表适合于不支持指针的高级语言,或者最大元素值固定但插入、删除操作频繁的链表操作中,有关基于静态链表的操作与动态链表的相同。

特点:

(1)所有数据元素均存储在一个连续的空间段,但是相邻两个元素不一定处于相邻的空间。

(2)修改指针域即可以完成插入和删除操作,不需要移动数据元素,但是也不能随机访问静态链表的元素。

(3)一次性分配所有存储空间,插入、删除时无需再向操作系统申请或释放空间,但也限制了最大表长。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值