单链表操作(C语言)含注释

1、创建

2、显示

3、查找(显示比较次数)

4、插入

5、删除(显示比较次数)

6、将链接存储线性表逆置,即最后一个结点变成第1个结点,原来倒数第2个结点变成第2个结点,如此等等。

7、生成有序的两个单链表A和B(链表的数据和个数自定),其首结点指针分别为a和b,要求将两个单链表合并为一个有序的单链表C,其首结点指针为c,并且合并后的单链表的数据不重复。

8、将一个首结点指针为a的单链表A分解成两个单链表A和B,其首结点指针分别为a和b,使得链表A中含有原链表A中序号为奇数的元素,而链表B中含有原链表A中序号为偶数的元素,且保持原来的相对顺序。

单链表操作菜单如下图所示:

以下已给出:

公用的等待函数

void wait()
{
    cout << "\n\n请按任意键继续" << flush;
    getch();
}

屏幕提示后,从键盘输入线性表长度和随机数种子,生成以DLList为头指针的指定长度的线性表

void init(Node *DLList)
{
    int length;
    Node *p,*q;
    while (1)
    {
        cout << "输入元素个数(0-" << 10000 << "):" << flush;
        cin >> length;
        if (length >= 0 && length <= 10000)
            break;
        cout << endl;
    }

        int i;
    while (1)
    {
        cout << "输入随机数种子(0-32767):" << flush;
        cin >> i;
        if (i >= 0 && i <= 32767)
            break;
        cout << endl;
    }

    //从线性表中删除并释放原有的结点,使其成为空表
    p=DLList;
    while (p->next!=NULL)
    {
        q=p->next;
        p->next=q->next;
        free(q);
    }

    srand(i);  //指定随机数种子,相同的种子将产生相同的数据序列
    rand();  

    //向线性表插入length个新结点
    for (int j=1;j<=length;j++)    
    {
        p=new Node;
        p->next=DLList->next;
        DLList->next=p;
        p->elem=rand() % 10000;
    }
}

一些个人感想:

我认为链表合并有些瑕疵,写的并不好;选择法排序那里不是很能理解透彻,个人认为可以偷懒,利用插入函数把一个个排好的数据插入一个新链表,在把旧链表等于新链表,但这样又不是很符合选择排序的思想。

这4行关键代码理解了蛮久的

temp=min->next;
min->next=temp->next;//将本循环的最小值从链表删除
temp->next=p->next;
p->next=temp;//将本循环的最小值插入链表

全部代码如下:

#include <iostream>
#include <iomanip>
#include <conio.h>
#include <stdio.h>
#include <process.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
using namespace std;

//定义结点类型
struct Node
{
    int elem;
    Node *next;
};

Node Head;       //头结点
Node *DLList;    //头指针

void init(Node *DLList);
void display(Node *DLList);
void insert(Node *DLList);
void search(Node *DLList);
void del(Node *DLList);
void wait();
void selectionSort(Node *DLList);
void listReverse(Node *DLList);
void listMerge(Node *DLList);
void listSplit(Node *DLList);

bool empty(Node *DLList);
void elemInsert(Node *DLList,int data);
int length(Node *DLList);

int main()
{
    char choice;

    DLList=&Head;     //使头指针指向头结点
    Head.next=NULL; 

    while (1)
    {
        system("cls");
        cout << "\n\n\n\n";
        cout << "\t\t              单链表操作  \n";
        cout << "\t\t======================================";
        cout << "\n\n";
        cout << "\t\t             1:初始化      \n";
        cout << "\t\t             2:显示        \n";
        cout << "\t\t             3:单个插入    \n";
        cout << "\t\t             4:查找        \n";
        cout << "\t\t             5:删除        \n";
        cout << "\t\t             6:选择法排序   \n";
        cout << "\t\t             7:逆置链表     \n";
        cout << "\t\t             8:合并两链表   \n";
        cout << "\t\t             9:拆分链表     \n";
        cout << "\t\t             0:退出        \n";
        cout << "\n";
        cout << "\t\t请选择:" << flush;

        choice = getch();
        system("cls");
        
        switch(choice)
        {
            case '1':
                init(DLList);
                wait();
                break;
            case '2':
                display(DLList);
                wait();
                break;
            case '3':
                insert(DLList);
                wait();
                break;
            case '4':
                search(DLList);
                wait();
                break;
            case '5':
                del(DLList);
                wait();
                break;
            case '6':
                selectionSort(DLList);
                wait();
                break;
            case '7':
                listReverse(DLList);
                wait();
                break;
            case '8':
                listMerge(DLList);
                wait();
                break;
            case '9':
                listSplit(DLList);
                wait();
                break;
            case '0':
                exit(0);
        }
    }
}

//公用的等待函数
void wait()
{
    cout << "\n\n请按任意键继续" << flush;
    getch();
}

//屏幕提示后,从键盘输入线性表长度和随机数种子,生成以DLList为头指针的指定长度的线性表
void init(Node *DLList)
{
    int length;
    Node *p,*q;
    while (1)
    {
        cout << "输入元素个数(0-" << 10000 << "):" << flush;
        cin >> length;
        if (length >= 0 && length <= 10000)
            break;
        cout << endl;
    }

        int i;
    while (1)
    {
        cout << "输入随机数种子(0-32767):" << flush;
        cin >> i;
        if (i >= 0 && i <= 32767)
            break;
        cout << endl;
    }

    //从线性表中删除并释放原有的结点,使其成为空表
    p=DLList;
    while (p->next!=NULL)
    {
        q=p->next;
        p->next=q->next;
        free(q);
    }

    srand(i);  //指定随机数种子,相同的种子将产生相同的数据序列
    rand();  

    //向线性表插入length个新结点
    for (int j=1;j<=length;j++)    
    {
        p=new Node;
        p->next=DLList->next;
        DLList->next=p;
        p->elem=rand() % 10000;
    }
}

//在屏幕上依次显示以DLList为头指针的线性表中的全部元素和元素个数
//格式应便于观察
//如果需要指定输出的宽度,可以使用 cout << setw(W) << X ,其中 X 是输出的数值,W 是占据的列数
void display(Node *DLList)
{
    if(empty(DLList))
        return;
    Node *p=DLList->next;
    int i=1;//控制换行
    while(p!=NULL)
    {
        cout <<setiosflags(ios::left)/*左对齐*/<< setw(15) << p->elem;
        if(i%10==0) printf("\n");
        i++;
        p=p->next;
    }
    printf("\n此表中共有%d个元素!\n",length(DLList));
    
}

//屏幕提示后,从键盘输入一个元素值,然后把这个新元素插到以DLList为头指针的线性表的末尾
void insert(Node *DLList)
{
    int i;
    Node *p=DLList,*temp;
    while(p->next!=NULL)
        p=p->next;
    temp=new Node;
    printf("请输入插入元素的值:");
    scanf("%d",&temp->elem);//数据域
    temp->next=NULL;//指针域
    p->next=temp;
    printf("插入成功!\n");
}

//屏幕提示后,从键盘输入一个元素值,在以DLList为头指针的线性表中搜索这个元素
void search(Node *DLList)
{
    if(empty(DLList))
        return;
    Node *p;
    p=DLList->next;
    int elem,count=0;
    printf("请输入查找元素值:");
    scanf("%d",&elem);
    while(p!=NULL)
    {
        count++;
        if(p->elem==elem)
        {
            printf("该元素在链表第%d位,共比较%d次\n\n",count,count);
            display(DLList);
            return;
        }
        p=p->next;
    }
    printf("链表无此元素!共比较%d次\n",count);
}

//屏幕提示后,从键盘输入一个元素值,在以DLList为头指针的线性表中删除这个元素
//屏幕显示删除成功与否的信息
void del(Node *DLList)
{
    Node *p,*s;
    if(empty(DLList))
        return;
    int delelem,count;
    printf("请输入要删除元素值:");
    scanf("%d",&delelem);
    while(p->next!=NULL)
    {
        count++;//比较次数
        if(delelem==p->next->elem)
        {
            s=p->next;//指向删除元素
            p->next=p->next->next;//覆盖
            printf("删除成功!,共比较%d次\n",count);
            free(s);//释放内存
            return;
        }
        p=p->next;
    }
    printf("链表无此元素!共比较%d次\n",count);
}
 
//选择法排序
void selectionSort(Node *DLList)
{
    if(empty(DLList))
        return;
    Node *p,*q,*min,*temp;
    p=DLList;
    while(p->next!=NULL)
    {
        q=p->next;
        min=p;
        while(q->next!=NULL)
        {
            if(q->next->elem < min->next->elem)
                min=q;
            q=q->next;
        }
        if(min!=p)
        {
            temp=min->next;
            min->next=temp->next;//将本循环的最小值从链表删除
            temp->next=p->next;
            p->next=temp;//将本循环的最小值插入链表
        }
        p=p->next;
    }
    printf("排序完成!");
}

//应用题

//6、将链接存储线性表逆置,即最后一个结点变成第1个结点,原来倒数第2个结点变成第2个结点,如此等等。
void listReverse(Node *DLList)
{
    if(empty(DLList))
        return;
    printf("逆置前:\n");
    display(DLList);
    Node *p,*q,*s;
    p=DLList->next;//p指向第一个元素
    q=p->next;//q指向第二个元素
    p->next=NULL;//p指针域为NULL,即链表尾部
    while(q)//判断
    {
        s=q->next;//未逆置部分
        q->next=p;//逆置
        p=q;//p保存
        q=s;//提取下一个
    }
    DLList->next=p;    
    printf("\n逆置后:\n");
    display(DLList);
}

/*7、生成有序的两个单链表A和B(链表的数据和个数自定),其首结点指针分别为a和b,要求将两
个单链表合并为一个有序的单链表C,其首结点指针为c,并且合并后的单链表的数据不重复。 
*/  
void listMerge(Node *DLList)
{
    if(empty(DLList))
        return;

    Node *DLList2;//链表2
    Node *DLList3;//最终表
    Node head2,head3;//头节点
    head2.next=NULL;head3.next=NULL;
    DLList2=&head2;
    DLList3=&head3;

    Node *p,*p2,*p3;
    printf("请设置顺序表2:\n");
    init(DLList2);
    selectionSort(DLList);
    selectionSort(DLList2);
    system("cls");
    p=DLList->next;
    p2=DLList2->next;
    p3=DLList3;
    //求交集并排序
    while(p!=NULL&&p2!=NULL)
    {
        if(p->elem==p2->elem)
        {
            elemInsert(DLList3,p->elem);
            p=p->next;
            p2=p2->next;
        }
        else if(p->elem<p2->elem)
        {
            elemInsert(DLList3,p->elem);
            p=p->next;
        }
        else
        {
            elemInsert(DLList3,p2->elem);
            p2=p2->next;
        }
    }
    //找到DLList的尾指针位置
    while(p3->next!=NULL)
        p3=p3->next;
    //尾部处理
    if(p==NULL)
        p3->next=p2;
    else if(p2==NULL)
        p3->next=p;
    
    printf("排序成功!\n");
    printf("表一:\n");
    display(DLList);
    printf("表二:\n");
    display(DLList2);
    DLList->next=DLList3->next;
    free(DLList3);//释放空间
    free(DLList2);//释放空间
    printf("新表:\n");
    display(DLList);
}
//8、将一个首结点指针为a的单链表A分解成两个单链表A和B,其首结点指针分别为a和b,使得链表A中含有原链表A中序号为奇数的元素,而链表B中含有原链表A中序号为偶数的元素,且保持原来的相对顺序。
void listSplit(Node *DLList)
{
    if(empty(DLList))
        return;

    Node *DLList_odd;//奇数链表
    Node *DLList_even;//偶数链表
    Node head_odd,head_even;//头结点
    head_odd.next=NULL;
    head_even.next=NULL;
    DLList_odd=&head_odd;
    DLList_even=&head_even;

    Node *p=DLList->next;
    int serial=1;//序号
    //判断奇偶
    while(p)
    {
        if(serial%2==0)
            elemInsert(DLList_even,p->elem);
        else 
            elemInsert(DLList_odd,p->elem);
        serial++;
        p=p->next;
    }
    printf("奇数:\n");    
    display(DLList_odd);
    printf("\n");
    printf("偶数:\n");
    display(DLList_even);
    free(DLList_odd);
    free(DLList_even);
}

//判断链表是否为空,true为空
bool empty(Node *DLList)
{
    Node *p;
    p=DLList;
    if(p->next==NULL)
    {
        printf("链表为空,请初始化!\n");
        return true;
    }    
    return false;
}

//输出链表长度
int length(Node *DLList)
{
    if(empty(DLList))
        return 0;
    Node *p=DLList;
    int length=0;
    while(p->next!=NULL)
    {
        length++;
        p=p->next;
    }
    return length;
}

//插入指定元素
void elemInsert(Node *DLList,int data)
{
    int i;
    Node *p=DLList,*temp;
    while(p->next!=NULL)
        p=p->next;
    temp=new Node;
    temp->elem=data;
    temp->next=NULL;//指针域
    p->next=temp;
}

猜你喜欢

转载自blog.csdn.net/m0_62925086/article/details/129151598