关闭

[置顶] 单链表

标签: 数据结构单链表
432人阅读 评论(0) 收藏 举报
分类:

现在已经进入专业课复习,王道的数据结构复习指导的第一个数据结构虽然是顺序表,但是过于简单,就不想写了。现在复习到链表,首先单链表数其他链表的基础。所以首先把单链表所有基础操作全部写一遍。包括建表,插入,删除,逆序,判断是否为空,合并等。我这里写的是带有头结点的单链表,头结点保存链表长度。


代码如下:

#include <iostream>
using namespace std;

//带头结点的单链表类,头结点存放单链表长度 
class Single_List{
    private:
        int data;
        Single_List* next;
    public: 
        //单链表的创建函数,尾插法 
        Single_List* Create(int len){
            Single_List* prev,*head,*tail;
            head = new Single_List;
            head->data = len;
            head->next = NULL;
            prev = head;
            if(len == 0){
                goto end;
            }
            cout<<"请输入各个结点的数值:"<<endl; 
            while(len--){
                int data;
                tail = new Single_List;
                cin>>data;
                this->attach(prev,tail,data); 
                prev = tail;
            }
            end:    return head;
        }

        void attach(Single_List* prev,Single_List* tail,int data){
            tail->next = NULL;
            tail->data = data;
            prev->next = tail;
        }

        int getLength(Single_List* list){
            return list->data;
        }

        //判断单链表是否为空的函数 
        bool Isempty(Single_List* list){
            return list->data == 0;
        }

        //单链表的打印函数
        void Print(Single_List* list){
            if(list->Isempty(list)){
                cout<<"单链表为空"<<endl;
                return;
            }
            int len = list->data;
            Single_List* ptrl = list->next;
            for(int i = 0 ; i < len ; i++){
                cout<<ptrl->data<<" ";  
                ptrl = ptrl->next;
            }
        }

        //在第index个结点后面插入数值为data的结点的函数 
        Single_List* Insert(Single_List* list,int index ,int data){
            Single_List* prev = list;
            Single_List* insert;
            insert = new Single_List;
            int len = list->getLength(list);
            //链表为空时,无论index为多少,只能插在第一个位置 
            if(this->Isempty(list)){
                this->attach(prev,insert,data);
                list->data++;
                return list;
            }
            //如果插入的位置大于等于链表长度直接插到末尾, 
            index = (list->data <= index)?list->data:index;
            for(int i = 0 ; i < index ; i++){
                prev = prev->next;
            }
            insert->data = data;
            insert->next = prev->next;
            prev->next = insert;
            list->data++;
            return list;
        }

        //寻找第k个结点的函数,只适用链表不为空的情况 
        Single_List* Findkth(Single_List* list ,int k){
            Single_List* prev;
            prev = list;
            for(int i = 0 ; i < k ; i++){
                prev = prev->next;
            } 
            return prev;
        }

        //寻找数值为N的结点的函数
        int FindN(Single_List* list,int N){
            int result = -1;
            Single_List* prev;
            prev = list;
            int len = this->getLength(list); 
            for(int i = 0 ; i < len ; i++){
                prev = prev->next;
                if(prev->data == N){
                    result = i;
                    break;
                }
            }
            return result; 
        }

        //删除数值为N的结点的函数 
        void DeleteN(Single_List* list,int N){
            int index = this->FindN(list,N);
            //不存在数值为N的情况 
            if(index == -1){
                cout<<"单链表不存在数值为"<<N<<"的结点"<<endl;
                return;
            }
            this->Deletekth(list,index+1);
        }

        //删除第k个结点的函数
        void Deletekth(Single_List* list,int k){
            int len = list->data;
            if(this->Isempty(list)){
                cout<<"单链表为空无法删除"<<endl;
                return; 
            }
            Single_List* del_pre;
            del_pre = this->Findkth(list,k-1);
            del_pre->next = del_pre->next->next;
            list->data--;
        }

        //逆转链表函数
        Single_List* Reverse(Single_List* list){
            //单链表为空时 
            if(this->Isempty(list)){
                return list;
            }
            Single_List* head,*front,*rear,*tag;
            head = list;                //保存头结点 
            //front,rear用于逆转,tag用于记录未逆转的链表 
            front = list->next;         
            rear = front->next;
            front->next = NULL;
            while(rear){
                tag = rear->next;
                rear->next = front;
                front = rear;
                rear = tag;
            }
            head->next = front;
            return head;
        }

        //对两个升序链表进行升序合并函数 
        Single_List* Merge(Single_List* list1,Single_List* list2){
            if(list1 == NULL){
                return list1;
            }
            if(list2 == NULL){
                return list2;
            }
            Single_List* list;          //建立合并链表的头结点,存放两个链表长度之和 
            list = new Single_List;
            list->data = list1->data+list2->data;
            list->next = NULL;
            Single_List* prev1,*prev2,*tail,*head,*tag;
            prev1 = list1->next;        //指向list32的第一个结点(不是存放长度的头结点,即头结点之后的结点)
            prev2 = list2->next;
            head = new Single_List;     //建立新链表的空头结点 
            tag = head;                 //保存空头结点的地址 
            head->next = NULL;           
            while(prev1 && prev2){
                tail = new Single_List;
                if(prev1->data <= prev2->data){
                    this->attach(head,tail,prev1->data);
                    head = tail;
                    prev1 = prev1->next;
                }else{
                    this->attach(head,tail,prev2->data);
                    head = tail;
                    prev2 = prev2->next;
                }
            }
            if(prev1){
                head->next = prev1;
            }
            if(prev2){
                head->next = prev2;
            }
            list->next = tag->next;
            return list;                    
        }

        //链表排序,冒泡排序
        Single_List* Sort(Single_List* list){
            Single_List* head,*prev1,*prev2;
            head = list;
            prev1 = list->next;
            while(prev1){
                prev2 = prev1->next;
                while(prev2){
                    if(prev1->data > prev2->data){
                        prev1->data += prev2->data;
                        prev2->data = prev1->data - prev2->data;
                        prev1->data -= prev2->data;
                    }   
                    prev2 = prev2->next;
                }
                prev1 = prev1->next;
            }
            return head;
        } 
};

int main()
{
    cout<<"请输入初始化单链表的长度:"<<endl;
    int len;
    Single_List tmp; 
    Single_List* list;
    cin>>len;
    list = tmp.Create(len);

    cout<<"单链表如下:"<<endl; 
    tmp.Print(list);
    cout<<endl;
    cout<<"排序后为:"<<endl;
    list = tmp.Sort(list);
    tmp.Print(list);
    cout<<endl;

    cout<<"请输入初始化单链表的长度:"<<endl;
    Single_List* list1;
    cin>>len;
    list1 = tmp.Create(len);
    cout<<"第二个单链表如下:"<<endl; 
    tmp.Print(list1);
    cout<<endl;
    cout<<"排序后为:"<<endl;
    list1 = tmp.Sort(list1);
    tmp.Print(list1);
    cout<<endl;

    cout<<"合并后链表为:"<<endl;
    Single_List* merge_list = tmp.Merge(list,list1);
    tmp.Print(merge_list);
    cout<<endl;


    cout<<"请输入插入结点的位置:"<<endl;
    int index,data;
    cin>>index;
    cout<<"插入前单链表如下:"<<endl; 
    tmp.Print(list);
    cout<<endl<<"请输入插入结点的数值:"<<endl;
    cin>>data;
    list = tmp.Insert(list,index,data);
    cout<<"插入后单链表如下:"<<endl; 
    tmp.Print(list);
    cout<<endl;


    cout<<"请输入删除结点的位置:"<<endl;
    cin>>index;
    cout<<"删除前单链表如下:"<<endl; 
    tmp.Print(list);
    tmp.Deletekth(list,index);
    cout<<endl<<"删除后单链表如下:"<<endl; 
    tmp.Print(list);
    cout<<endl;

    cout<<"请输入删除结点的数值:"<<endl;
    cin>>data;
    cout<<"删除前单链表如下:"<<endl; 
    tmp.Print(list);
    tmp.DeleteN(list,data);
    cout<<endl<<"删除后单链表如下:"<<endl; 
    tmp.Print(list);
    cout<<endl;

    cout<<"逆转单链表前,单链表如下:"<<endl;
    tmp.Print(list);
    cout<<endl<<"逆转单链表后,单链表如下:"<<endl;
    list = tmp.Reverse(list); 
    tmp.Print(list); 

    return 0;
 } 

代码和截图有点不一样,因为功能写的太多了,每个功能截个图,但把所有功能跑一边很麻烦。所以截图是只运行了一个功能,其他给注释了,请谅解。
创建与排序功能:
链表为空时(这里不包含头结点)
这里写图片描述
链表不为空时
这里写图片描述


合并功能(这里是2个升序序列的合并
这里写图片描述


插入功能:
链表为空时的插入:
这里写图片描述
插入到链表末尾的情况,此时链表非空:
这里写图片描述
插入到中间的情况:
这里写图片描述


按位置删除的情况:
这里写图片描述


按值删除的情况:
这里写图片描述


逆序功能:
这里写图片描述

1
0
查看评论

Java中单链表的描述与对单链表的各种操作

首先创建结点类的描述/** * 结点类的描述 * * 单链表是由若干个结点连接而成,要实现单链表,首先需要设计结点类 * * 结点类由data和next组成 * * data是数据域,用来存放数据元素的值 * next是指针域,用来存放后继结点的地址 * * @autho...
  • awozuiniu
  • awozuiniu
  • 2015-08-24 10:51
  • 1480

单链表的实现(C++版)

// 带头节点单链表的C++实现 #include "stdafx.h" #include #include using namespace std; class CNode //节点 { public: int dat...
  • piaopiaopiaopiaopiao
  • piaopiaopiaopiaopiao
  • 2014-05-12 20:27
  • 6635

单链表的建立,实现和操作

文中引用了一个单链表就地逆序的算法,在下资质愚钝想了半天没想出来,感谢这位仁兄的分享点击打开链接 #include #include #include #include #include using namespace std; typedef struct LNode { int dat...
  • bengshakalakaka
  • bengshakalakaka
  • 2017-03-17 18:35
  • 3955

单链表、双链表、循环链表总结

1.单链表(为升序链表,value按升序排列) #include #include typedef struct NODE { struct NODE *link; int value; } Node;//最好放在头文件中 Node *sll_creat(); int ...
  • SdustLiYang
  • SdustLiYang
  • 2012-01-12 16:51
  • 3632

单链表之排序

题:编程实现单链表的排序。 答案:完整代码如下: // P167_example1.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include #in...
  • jimoshuicao
  • jimoshuicao
  • 2013-07-30 16:40
  • 2990

2015年大二上-数据结构-链表(3)-单链表算法

1、设计一个算法,将一个带头结点的数据域依次为a1,a2,…,an(n≥3)的单链表的所有结点逆置,即第一个结点的数据域变为an,…,最后一个结点的数据域为a1。实现这个算法,并完成测试。 /* *Copyright (c) 2014,烟台大学计算机学院 *All rights reserved. ...
  • Annpion
  • Annpion
  • 2015-11-03 12:28
  • 431

单链表操作之合并两个单链表

***单链表操作之合并两个单链表*** /*  本篇博客为合并两个单链表, 有序和无序都可以; 其中用到单链表的尾插和单链表的选择排序; @单链表排序之选择排序链接:http://blog.csdn.net/bitboss/article/details/5160254...
  • bitboss
  • bitboss
  • 2016-06-08 14:01
  • 5265

单链表----java语言实现

节点   数据域:存放数据   指针域:存放下一个数据的地址 1、常用操作   查找   插入   删除 查找: (1)按照索引查找index位置上的节点:从头节点head开始依次向下找到第index...
  • snow_7
  • snow_7
  • 2016-06-07 15:43
  • 685

单链表基本操作详解

#  单链表基本操作 文中提到的内容的链接一并列在这里: 顺序表:http://blog.csdn.net/bitboss/article/details/51559175 冒泡排序:http://blog.csdn.net/bitboss/article/details/...
  • bitboss
  • bitboss
  • 2016-06-04 22:12
  • 2872

第1章第2节练习题8 奇偶拆分单链表

将一个带头结点的单链表分解为两个带头结点的单链表A和B,使得A表中含有原表中序号为奇数的元素,而B表中含有元表中序号为偶数的元素,且保持其相对顺序不变。
  • u013595419
  • u013595419
  • 2016-01-11 16:21
  • 1264
    个人资料
    • 访问:155740次
    • 积分:4932
    • 等级:
    • 排名:第6843名
    • 原创:329篇
    • 转载:0篇
    • 译文:0篇
    • 评论:81条
    博客专栏
    最新评论