C语言/C++链表知识浅谈

c语言链表知识浅谈

引言

链表相比于数组的优越在于链表的元素独立性较强,易于频繁插入或删除数据元素;缺点在于其不稳定性较大。

基础知识

在线性表中,每个结点只需要存放后继结点的地址,让一个个元素串联起来,就能够形成一个“单向链表”
单向链表的结构体为

struct Node{
datatype data;
Node*next;
};

建立链表的过程可以描述为
生成头结点:
while(未结束){
生成新结点;
把新结点插入链表;}

链表处理

建立单向链表

c++有new和delete函数,更利于申请和释放空间

struct node{
    int data;
    node*next;
};
void CreateList(node*&head){//引用的参数是表头指针
    node*s,*p;
    s=new node;
    cin>>s->data;
    while(s->data!=0){
        if(head==NULL)head=s;//如果没有head,则插入head
        else p->next=s;
        p=s;
        s= new node;//new函数为node重新分配内存
        cin>>s->data;
    }
p->next=NULL;
delete s;//释放堆内存
return;}

c语言无new,delete函数,一般是用malloc函数和free函数

typedef struct node{
    int data;
    node*next;
}Node;//为struct起个别名为Node
void CreateList(Node*&head){
    Node *s,*p;
    s=(Node*)malloc(sizeof(Node));
    scanf("%d",&s->data);
    while(s->data!=0){
        if(head==NULL)head=s;
        else p->next=s;
        p=s;
        s=(Node*)malloc(sizeof(Node));
        scanf("%d",&s->data);
    }
    p->next=NULL;
    free(s);
    return;
}


遍历链表

遍历链表从表头指针开始,使用跟踪指针逐个输出结点值,直至指针为空

while(head){
printf("%d ",head->data;
head=head->next;
}

插入结点

步骤

  1. 生成新结点
  2. 把新结点连接上链表
  3. 修改表头指针
    伪代码如下
current = head, k = 0
if position is 0, insert num before head and return
while current != null
    if position = k + 1
        insert num after current
    current = current.next, k ++

实例:用插入法生成有序链表

#include<iostream>
using namespace std;
struct List{
    int data;
    List*next;
};
int main(){
int k;
List*head=NULL;
cin>>k;
while(k!=0){
    List*s,*p,*q;int b=1;
    s=new List;
    s->data=k;
    s->next=NULL;
    if(head==NULL)head=s;//若表空,则建立一个结点的链表
    else if(head->data>s->data){//被插数据最小,插入表头
            s->next=head;
            head=s;
        }
    else {
        for(q=head,p=head->next;p;q=p,p=p->next){
            if(p->data>s->data){
                s->next=p;
                q->next=s;b=0;break;
            }
        }
        if(b)q->next=s;
    }
}
while(head){
    cout<<head->data<<" ";
    head=head->next;
}
return 0;
}

链表查找元素

伪代码如下

current = head
return head if head.value is number
while current.next != null
    current = current.next
    if current.value is number
       return current

即为

for(p=head;p;p=p->next,i++){
        if(k==p->data)break;
    }
    printf("%d在链表中的第%d位",k,i)

删除结点

伪代码为

if position is 0, head = head.next & return
current = head, k=0
while current.next != null
  if position is k + 1
    current.next=current.next.next
  current = current.next, k ++

实例:从链表中删除值等于key的结点
这里我们构造一个函数

void del(List*&head,int key){
    List*p;
    if(!head){printf("List is null");return;}
    if(head->data==key){
        p=head; head=head->next;
        delete p;p=NULL;return;
    }
    for(List*i=head;i->next;i=i->next){
        if(i->next->data==key){
            p=i->next;
            i->next=p->next;
            delete p;
            p=NULL;
        }
    }
}

经典例题

计算理工学院有 N 个同学,围成了一个圆圈,每人被顺序地编了一个序号(分别为 1,2,3…n),从编号为 K 的人开始报 11,他之后(顺初始数字增长方向计算序号)的人报 2,以此类推,数到某一个数字 M 的人出列。出列同学的下一个人又从 1开始继续报数,数到某一个数字 M的人出列。不断重复这一过程,直到所有人都出列为止。
输入格式
测评机会反复运行你的程序。每次程序运行时,输入为一行,包括三个被空格分隔开的符合描述的正整数 N、K 和 M(10001≤K≤N≤1000, 20001≤M≤2000)

#include <stdio.h>
#include <stdlib.h>
typedef struct node {
    int data;
    struct node *next;
} Node;

Node *circle_create(int n);
void count_off(Node *head, int n, int k, int m);

int main() {
    int n, k, m;
    scanf("%d%d%d", &n, &k, &m);
    Node *head = circle_create(n);
    count_off(head, n, k, m);
    return 0;
}

Node *circle_create(int n) {
    Node *temp, *new_node, *head;
    int i;

    // 创建第一个链表节点并加数据
    temp = (Node *) malloc(sizeof(Node));
    head = temp;
    head->data = 1;

    // 创建第 2 到第 n 个链表节点并加数据
    for(i = 2; i <= n; i++) {
        new_node = (Node *) malloc(sizeof(Node));
        new_node->data = i;
        temp->next = new_node;
        temp = new_node;
    }

    // 最后一个节点指向头部构成循环链表
    temp->next = head;

    return head;
}

void count_off(Node *head, int n, int k, int m) {
        Node *p, *q;
        p = head;
        q = head;
        for (; p->next != head; p = p->next);
        for (int i = -k + 2; q != q->next; i++,p=q,q=q->next) {
            if (i == m) {
                printf("%d ", q->data);
                p->next = q->next;
                free(q);
                q = p;
                i = 0;
            }
        }
        printf("%d", q->data);
    }


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值