数据结构之链表操作


#include <IOSTREAM>
#include <IOMANIP>
#include <STRING>
using namespace std;

typedef struct Student
{
    int id;
    char name[20];
    char sex[20];
    struct Student *next;
}node;
typedef node * pnode;
pnode Create();
void Print(pnode h);
void Sort(pnode h);
int Length(pnode h);
void Delete(pnode h,int num);
void Insert(pnode h,int num,char * name,char * sex);

int main()
{
    char command[10] = "1";
    pnode h;
    while(strcmp(command,"q")!=0)
    {
        cout << "请输入命令:" << endl;
        cout <<"-----------------------------"  << endl;
        cout <<"1: 创建链表"  << endl;
        cout <<"2: 插入节点"  << endl;
        cout <<"3: 删除节点"  << endl;
        cout <<"4: 链表排序"  << endl;
        cout << "5:打印链表" << endl;
        cout << "6:链表长度" << endl;
        cout <<"q:退出" << endl;
        cout <<"-----------------------------"  << endl;

        cin >> command;
        if(0==strcmp(command, "1"))
        {
            h = Create();
            Print(h);
        }
        else if(0==strcmp(command, "2"))
        {
            cout << "请输入学号,姓名,性别:\n";
            node temp;
//             cin >> temp.id ;
//             getchar();
//             cin.getline(temp.name,20);
//             cin.getline(temp.sex,20);
            temp.id = 10;
            strcpy(temp.name , "weilele");
            strcpy(temp.sex, "female");
            Insert(h,temp.id,temp.name,temp.sex);

        }
        else if(0==strcmp(command, "3"))
        {

        }
        else if(0==strcmp(command, "4"))
        {
            Print(h);
        }
        else if(0==strcmp(command, "5"))
        {
            Print(h);
        }
        else if(0==strcmp(command, "6"))
        {
            cout << "链表长度:" << Length(h) << endl;
        }

    }

    return 0;
}

pnode Create()
{
    pnode h;
    pnode p,q;
    bool flag = true;

    //建立一个头节点
    h = new node;
    h->id=0;
    strcpy(h->name,"none");
    h->next = NULL;
    p=h;

    int id;
    char name[20];
    char sex[20];
    //注意这里的cin无法直接读取空格隔开的元素的值
    //将数字转换成字符串?

    while (flag)
    {
        cout << "请输入学生的学号,姓名,性别:\n"  << endl;
        string str1;
        string str2;
        string str3;
        char temp;
        cin>> id ;
        char c = getchar();
        cin.getline(name,20);   // 读取一行数据,允许中间出现空格
        cin.getline(sex,20);
        //cin >> id;            

        if(id!=0)
        {
            q = new node;
            q->id = id;
            strcpy(q->name,name);
            strcpy(q->sex,sex);

            q->next = NULL;

            p->next = q;
            p=p->next;
        }

        else   //退出输入
        {
            flag = false;
        }
    }

    return h;
}

void Print(pnode h)
{
    pnode q= h->next;
    if(q==NULL)
    {
        cout << "链表为空!" << endl;
        return;
    }

    cout << "打印链表:" << endl;
    int i=0;
    while(q!=NULL)
    {
        cout <<  "节点"<<i++ << "\t"<< "学号:"<< q->id << "姓名:"<<  q->name <<"性别:"<< q->sex << endl;
        q=q->next;
    }

}

int Length(pnode h)
{
    pnode p=h->next;
    int n = 0;
    while(p!=NULL)
    {
        n++;
        p = p->next;
    }
    return n;
}

void Delete(pnode h,int num)
{
    pnode p1 = h->next;
    pnode p2;
    if(p1==NULL)
    {
        cout << "链表为空!无法查找"  << endl;
        return;
    }

    while (p1->id!=num && p1->next != NULL)
    {
        p2= p1;
        p1 = p1->next;
    }

    if(p1->id == num)
    {
        if(p1 == h)     //在h头
        {
            p1 = h;
            h = h->next;
            delete p1;   //释放掉头节点
        }
        else if (p1->next == NULL)
        {
            delete p1;
            p2->next = NULL;
        }
        else
        {
            p2->next = p1->next;
            delete p1;
        }
        cout << "删除节点成功" << endl;
    }
    else
    {
        cout << "没有查找到对应节点,无法删除\n";
    }
}

void Sort(pnode h)
{
    if(h == NULL)
    {
        cout << "链表为空!无需排序" <<endl;
        return;
    }
    pnode p,q;
    p=h->next;
    while(p->next!=NULL)
    {
        q=p->next;
        while(q!=NULL)
        {
            if(q->id < p->id)
            {
                node temp;
                temp.id= p->id;
                strcpy(temp.name , p->name);
                strcpy(temp.sex, p->sex);

                p->id = q->id;
                strcpy(p->name, q->name);
                strcpy(p->sex,q->sex);

                q->id = temp.id;
                strcpy(q->name,temp.name);
                strcpy(q->sex,temp.sex);

            }
            q = q->next;
        }
        p = p->next;
    }
    cout << "排序完成,输出:" << endl;
    Print(h);

}

//插入操作,这里插入操作如果是在头节点之前会出现错误,所以要给链表一个头节点来避免错误//原因:这里函数的形参h是指针的值传递,在退出该函数后,指针的值并没有发生变化,因为传递的只是一份形参。在Insert中的所有操作是对指针的值的拷贝的操作,在函数中改变指针的值(h=s)其实是对h的拷贝的改变,所以函数执行完后,原来实参的值并没有发生改变//
void Insert(pnode h,int num,char * name,char * sex)
{
    pnode p1,p2;
    p1 =h->next;
    pnode s = new node;
    s->id = num;
    strcpy(s->name,name);
    strcpy(s->sex ,sex);
    if(h== NULL)
    {
        h = s;
        cout  << "插入成功" << endl;
            Print(h);
        return;
    }

    while (p1->id<s->id && p1->next!=NULL)
    {
        p2 = p1;
        p1 = p1->next;
    }

    if(p1==h->next)
    {
        if(p1->id>s->id)
        {
            h->next = s;
            s->next = p1;
        }
        else
        {
            p1->next = s;
            s->next = NULL;
        }

    }
    else if(p1->next == NULL)
    {
        p1->next = s;
        s->next = NULL;
    }
    else
    {
        p2->next = s;
        s->next = p1;
    }
    Print(h);

}

数据结构中,在单链表的开始结点之前附设一个类型相同的结点,称之为头结点。头结点的数据域可以不存储任何信息,头结点的指针域存储指向开始结点的指针(即第一个元素结点的存储位置)。

作用

1、防止单链表是空的而设的.当链表为空的时候,带头结点的头指针就指向头结点.如果当链表为空的时候,单链表没有带头结点,那么它的头指针就为NULL.

2、是为了方便单链表的特殊操作,插入在表头或者删除第一个结点.这样就保持了单链表操作的统一性!

3、单链表加上头结点之后,无论单链表是否为空,头指针始终指向头结点,因此空表和非空表的处理也统一了,方便了单链表的操作,也减少了程序的复杂性和出现bug的机会。

4、对单链表的多数操作应明确对哪个结点以及该结点的前驱。不带头结点的链表对首元结点、中间结点分别处理等;而带头结点的链表因为有头结点,首元结点、中间结点的操作相同 ,从而减少分支,使算法变得简单 ,流程清晰。对单链表进行插入、删除操作时,如果在首元结点之前插入或删除的是首元结点,不带头结点的单链表需改变头指针的值,在C 算法的函数形参表中头指针一般使用指针的指针(在C+ +中使用引用 &);而带头结点的单链表不需改变头指针的值,函数参数表中头结点使用指针变量即可。

时间: 2024-11-10 04:06:46

数据结构之链表操作的相关文章

数据结构上机测试2-1:单链表操作A (顺序建表+关键字删除)

数据结构上机测试2-1:单链表操作A Time Limit: 1000MS Memory limit: 4096K 题目描述 输入n个整数,先按照数据输入的顺序建立一个带头结点的单链表,再输入一个数据m,将单链表中的值为m的结点全部删除.分别输出建立的初始单链表和完成删除后的单链表. 输入 第一行输入数据个数n: 第二行依次输入n个整数: 第三行输入欲删除数据m. 输出 第一行输出原始单链表的长度: 第二行依次输出原始单链表的数据: 第三行输出完成删除后的单链表长度: 第四行依次输出完成删除后的

数据结构之链表单向操作总结

链表是数据结构的基础内容之一,下面就链表操作中的创建链表.打印链表.求取链表长度.判断链表是否为空.查找结点.插入结点.删除结点.逆转链表.连接链表.链表结点排序等进行总结. 1.创建表示结点的类,因为链表操作中需要比较结点,因此结点需要实现comparable接口. public class Node implements Comparable<Node> { private Object data; private Node next; //构造函数 public Node() { thi

数据结构之 线性表---单链表操作A (删除链表中的指定元素)

数据结构上机测试2-1:单链表操作A Time Limit: 1000MS Memory limit: 4096K 题目描述 输入n个整数,先按照数据输入的顺序建立一个带头结点的单链表,再输入一个数据m,将单链表中的值为m的结点全部删除.分别输出建立的初始单链表和完成删除后的单链表. 输入 第一行输入数据个数n: 第二行依次输入n个整数: 第三行输入欲删除数据m. 输出 第一行输出原始单链表的长度: 第二行依次输出原始单链表的数据: 第三行输出完成删除后的单链表长度: 第四行依次输出完成删除后的

【数据结构与算法】java链表操作

链表操作代码量少但是比较容易出错,是比较适合面试的地方. 代码实现 /** * 源码名称:MyLinkList.java * 日期:2014-09-05 * 程序功能:java链表操作 * 版权:[email protected] * 作者:A2BGeek */ import java.util.Stack; public class MyLinkList { class LinkNode<T> { private T mValue; private LinkNode<T> mNe

数据结构之——链表(list)、队列(queue)和栈(stack)

在前面几篇博文中曾经提到链表(list).队列(queue)和(stack),为了更加系统化,这里统一介绍着三种数据结构及相应实现. 1)链表 首先回想一下基本的数据类型,当需要存储多个相同类型的数据时,优先使用数组.数组可以通过下标直接访问(即随机访问),正是由于这个优点,数组无法动态添加或删除其中的元素,而链表弥补了这种缺陷.首先看一下C风格的单链表节点声明: 1 typedef struct _ListNode{ 2 int val; 3 struct _ListNode *next; 4

链表操作 -- 有环链表问题

参考: http://blog.163.com/[email protected]/blog/static/1113522592011828104617420/ 问题: 判断一个链表中是否有环. 分析: 我们都知道,当一个链表中没有环时,我们使用一个指针能从头遍历到尾:当链表中有环时,链表会在环中旋转. 当我们只使用一个链表指针时,可想到方法就是使用额外的数据结构来存储遍历过的每个节点,在遍历next节点时,判断next节点是否已存在于存储的节点中. 存储结构可以选择为hashTable,这样的

C# 链表操作

关于链表操作,在C#当中微软已经提供了一个LinkedList<T>的数据结构,通过这个类提供的一系列方法就能够实现链表操作. 这里我提供一段代码,这是在论坛里面有人提问时给出的代码,它实现了自定义链表的操作(读者可以在此基础上进一步完善).因为这段代码涉及一些C#技巧,所以贴出来给初学者学习C#提供一点参考. 实体类:     /// <summary>     /// 学生类     /// </summary>     public class Student  

JAVA 链表操作:单连表和双链表

主要讲述几点: 一.链表的简介 二.链表实现原理和必要性 三.单链表示例 四.双链表示例 一.链表的简介 链表是一种比较常用的数据结构,链表虽然保存比较复杂,但是在查询时候比较便捷,在多种计算机语言都相应的应用,链表有多种类别,文章针对单链表和双链表进行分析.链表中数据就像被一个链条串联一起,轻易的可以实现数据的访问. 二.链表实现原理和必要性 这里只分析单链表和双链表.链表的实现过程是有些许复杂的,但是会带来许多好处.比如现在网购时代到来,商家发快递一般会将商品包装在盒子里并写上地址信息,快递

数据结构=。= 链表

为了工作,开始漫漫路 链表结构 数据部分:数据 地址部分:下一个结点地址 链表结构 typedef struct Data //Data数据结构 { char key[10]; //关键字 char name[20]; // int age; } typedef struct Node //结点结构 { Data nodeData; struct Node * next; }ListNode; 链表操作 链表操作中涉及到“增”结点的操作就要先分配空间 追加尾结点 步骤: 分配空间 检查是否为头指