单链表的基本运算

一、链表的简介
链表是一组任意的存储单元来存放线性表的结点,这组存储单元可以是连续的,也可以是不连续的,可以零散的分布在内存中的任意位置上。因此,链表中的逻辑次序和物理次序是不一定相同的。为了能正确表示结点的逻辑关系,在存储每个结点的同时,还必须存储指示其后继结点的地址信息,因此,链表中的结点结构由data(数据域)与next组成(指针域)。
单链表是链表的一种,这里只讲述关于单链表的一些简单的操作:创建、查找、插入以及删除。
二、单链表的创建
创建链表分有头结点与无头结点之分,动态的创建链表通常又分头插法和尾插法建表。
有头结点的链表相比五头结点的链表存在两个优势:
(1)由于开始结点的位置被存放在头结点的指针域中,所以链表的第一个位置上的操作就和在表的其他位置上的操作一致,就无需特殊处理。
(2)无论链表是否为空,其头指针是指向头结点的非空指针,因此空表与非空表的处理就同一了。
头插法建表与尾插法建表相比,两者存在这样的差别:头插法建表虽然简单,但生成的链表中结点的次序和输入顺序相反。若希望两者次序一致,可采用尾插法建表。尾插法建表必须增加一个尾指针,使其始终指向前链表的尾结点。
综上所述,本人根据个人喜好,在博客中的实例采用的是带头结点的尾插法建表。
尾插法建表的步骤如下:
(1)定义链表结点结构体
按照链表结点的特征,内容为data(数据域)+next(指针域),我们可以用C这样描述单链表:

typedef int datatype;
//节点类型定义
typedef struct node{
    datatype data;
    struct node *next;
}linklist;
linklist *head,*p;  /*指针类型说明*/

(2)建立头结点
建立头结点一般分三步:
a.为头结点申请内存空间,C语言表示为:p = malloc(sizeof(linklist));
b.将头结点指针域清空、尾指针指向头结点。
(3)加入节点
加入新的节点与建立头结点有些相似,大体步骤如下:
a.为新节点申请内存空间(listnode*)malloc(sizeof(listnode));
b.给结点内部赋值;
c.将前一个节点的指针域指向新节点;
d.将标志位一道新结点;
e.如果是最后一个结点,需要将该节点的指针域清空。
三、单链表的查找
单链表的查找有两种:按值查找与按位置查找。
1、按位置查找
在链表中,技师知道被访问的结点的序号i,也不能像顺序表中那样直接按序号i访问结点,而只能从链表的头结点出发,顺链域逐个结点往下查找,知道查找到第i个位置为止。因此,链表不是随机存取结构。
2、按值查找
安置查找首先按照按位置查找的思想遍历整个链表,查找是否有结点值等于给定值key的结点。查找过程从开始结点出发,顺着链逐个将结点的值跟给定值比较。
四、单链表的插入
与创建单链表相类似,结点的插入也分前插与后插,两者并没有太多的区别,但必须都要生成的的结点,然后修改相应的指针,最后进行插入。本文实例采用的是后插法插入新的结点,插入运算的步骤如下:
1、判断插入位置是否合法
2、创建新结点q且为其赋值(上文已有,不再赘述);
3、找到需要插入的位置(i)的前一个位置p(i-1);
4、将新节点插在p之后,调整指针域,将原先p的指针域赋值给q,然后将jiang p的指针域内容换成q的地址。
五、单链表的删除
删除结点与结点的插入相类似,可以直接条畅指针域实现,但有一点非常重要,在删除完结点之后需要释放该节点的内存空间(free(p)),具体步骤如下:
1、判断位置是否合法;
2、找到删除位置的前一位i-1;
3、将i-1的指针域指向i+1;
4、释放原先i位置上结点的内存空间。
六、实例:create_list.c

/*************************************************
Date:2015-5-24 13:08
Filename:create_list.c
Author:Chen liusuo
E-mail:liusuochen@gamil.com
Describe:单向链表的创建、插入、删除、查找、输出
*************************************************/

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

//结点结构体定义
struct Node
{
    char name[10];
    int score;
    struct Node *next;
};

//函数声明
typedef struct Node ListNode;

//尾插法建立链表
ListNode *CreateList(int total)
{
    ListNode *head;  /*头节点指针*/
    ListNode *p,*r;  
    int i;

    //链表初始化
    head = (ListNode*)malloc(sizeof(ListNode)); /*为头节点申请内存空间*/
    head->next = NULL; /*将头节点的指针域清空*/
    r = head;            /*尾指针初值指向头节点*/

    //通过for循环加入新节点 
    for ( i=1; i<=total; i++){
        p = (ListNode*)malloc(sizeof(ListNode));/*为要插入的新节点分配内
                            存空间*/
        printf("input name of the %d student\n",i);
        printf("input name of the student:");
        scanf("%s",p->name);
        printf("input score of the student:");
        scanf("%d",&p->score);
        r->next = p;    /*将p指向新节点插入链表指向的下个节点*/
        r = p; /*用于指向下一个节点*/
    }   
    p->next = NULL; /*最后将最后一个节点的指针域清空*/
    return head;    /*返回链表的首地址*/
}

//链表打印函数
void PrintList(ListNode *h)
{
    ListNode *p;
    p = h->next;
    while(p){
        printf("%s,%d",p->name,p->score);
        p = p->next;
        printf("\n");
    }
}

//按位置查找节点,若找到则返回位置P,否则返回NULL
ListNode *GetNodeByNum(ListNode *h,int location)
{
    int j = 0;
    ListNode *p;
    p = h;
    while(p->next && j<location){
        p = p->next;
        j++;
    }
    if(j==location){
        return p;
    }else{
        return NULL;
    }
}

//按内容查找,若找到则返回该节点的存储位置
ListNode *GetNodeByKey(ListNode *h,char name[])
{
    int j = 0;
    ListNode *p;
    p = h;
    while(p != NULL){
        if(p->name != name){
            p = p->next;
        }else{
            break;          
        }
        return p;
    }
}

//查找调用函数
void Get(ListNode *h)
{
    int choice;
    int location;
    char name[10];
    printf("1.按值查找\n");
    printf("2.按位置查找\n");
    scanf("%d",&choice);
    switch(choice){
        case 1:
            printf("Please input the name of student:");
            scanf("%s",name);
            GetNodeByKey(h,name);
            break;

        case 2:
            printf("Please input the num of student:");
            scanf("%d",&location);
            GetNodeByNum(h,location);
            break;

        default:
            break;
    }
}


//链表节点插入函数
void InsertList(ListNode *h,int location,char name[],int score,int total)
{
    ListNode *q,*p; //定义2个指向一个节点的指针
    int j;
    if(location<1 || location>total+1)
        printf("Error!Please input again.\n");
    else{
        j = 0;
        p = h;
        //找到i-1的位置
        while(j < location-1){
            p = p->next;
            j ++;
        }
        q = (ListNode*)malloc(sizeof(ListNode));

        //节点数据赋值
        strcpy(q->name,name);
        q->score = score;

        //调整指针域
        q->next = p->next;
        p->next = q;
    }
}

//链表删除函数
void DeleteList(ListNode *h,int location,int total)
{
    ListNode *p,*q;
    int j;
    char name[10];
    int score;
    if(1<location || location>total){
        printf("Error! Please input again.\n");
    }else{
        j = 0;
        p = h;
        //找到i-1的位置
        while(j< location-1){
            p = p->next;
            j ++;
        }
        q = p->next;/*q指向要删除位置*/
        p->next = q->next;
        strcpy(name,q->name);
        score = q->score;

        free(q);
        printf("Delete name=%s,score=%d\n",name,score);
    }

}

void main()
{
    ListNode *h;//h指向结构体NODE
    int choice ,total ,location,score; /*定义选项、节点数量、位置、分数*/
    char name[10];
    while(1){
        printf("--------------------------\n");
        printf("1.建立新的链表\n");
        printf("2.添加元素\n");
        printf("3.删除元素\n");
        printf("4.查找元素\n");
        printf("5.输出当前表中的元素\n");
        printf("0.退出\n");
        printf("--------------------------\n");     

        scanf("%d",&choice);
        switch(choice){
            case 1:
                printf("The number of Node:");
                scanf("%d",&total);
                h = CreateList(total);
                printf("list elements is:\n");
                PrintList(h);
                break;

            case 2:
                printf("input the position of insert elements:");
                scanf("%d",&location);
                printf("input name of the student:");
                scanf("%s",name);
                printf("input score of the student:");
                scanf("%d",&score);
                InsertList(h,location,name,score,total);
                PrintList(h);
                break;

            case 3:
                printf("input the position of delete element:");
                scanf("%d",&location);
                DeleteList(h,location,total);
                printf("list elements in:\n");
                PrintList(h);
                break;

            case 4:
                Get(h);
                break;

            case 5:
                printf("list elements is:\n");
                PrintList(h);
                break;

            case 0:
                return;
                break;

            default:
                printf("Error! Try again!\n");
        }
    }   
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值