单链表合并排序实现

原题是要实现两个已排序的单链表合并后还是已排序,但我在网上查了很多都无法直接实现.对于初学者给个算法是没多大用的,下面给出完整代码.主要思路就是先接尾再排序.而一般书是直接开始分情况if...else if...else嵌套排序.比较复杂.

/*关键:两个有序单链表的合并:其实本程序可以实现任意两个单链表的合并排序,思想就是

*1.建两个链表2.合并两个链表3.对合并后的链表排序4.打印

*关键函数:linkDList 直接连接两个链表;selectsort 单链表的选择排序*/

#define _CRT_SECURE_NO_WARNINGS

#include "stdio.h"

#include "malloc.h"

#include "windows.h"//system()所在

typedef char ElemType;    

typedef struct dNode

{//声明单链表结点类型

    ElemType data;    //数据域,注意此单链表结点类型是字符型.有什么办法可以泛化呢?

    struct dNode *next;    //指针域

}LNode, *LinkList;    //定义此结构体变量struct dNode a或LNode a;定义此结构体的指针struct dNode *p或LNode *p或LinkList p都是没区别的



//此函数本程序没用到,只是为了和后面的CreateDListTail对应

LinkList CreateDListHead(LinkList head)

{

    ElemType temp;

    LinkList p;

    printf("请输入结点值");

    fflush(stdin);

    scanf("%c", &temp);

    while (temp!='0')

    {

        if (('A' <= temp&&temp <= 'Z') || ('a' <= temp&&temp <= 'z'))

        {

            p = (LinkList)malloc(sizeof(LNode));

            p->data = temp;

            p->next = head->next;

            head->next = p;    

        }

        printf("请输入结点值(输入0结束):");

        fflush(stdin);

        scanf("%c", &temp);

    }

    return head;

}

LinkList CreateDListTail(LinkList Tail)  //尾插法建立链表  

{

    ElemType temp;

    LinkList s, r;

    printf("请输入结点值");

    fflush(stdin);

    scanf("%c", &temp);

    r = Tail;

    while (temp!='0')

    {

        if (('A' <= temp&&temp <= 'Z') || ('a' <= temp&&temp <= 'z'))

        {

            s = (LinkList)malloc(sizeof(LNode));

            s->data = temp;

            r->next = s;

            r = s;

        }    

        printf("请输入结点值(输入0结束):");

        fflush(stdin);

        scanf("%c", &temp);

    }

    r->next = NULL;

    return Tail;

}

void PrintDList(LinkList head)

{

    LinkList p;

    int i = 0;

    p = head->next;//p指向第一个结点.这一步原head后的结点都会跑到p后

    while (p != NULL)

    {

        i++;

        printf("第%d个元素是:", i);

        printf("%c\n", p->data);

        p = p->next;

    }

    printf("\n");

}

void linkDList(LinkList S, LinkList T)

{/*连接2个单链表*/

    LinkList temp = S;

    while (temp->next != NULL)

        temp = temp->next;

    temp->next = T->next;

    PrintDList(S);

}

void selectsort(LinkList A)

{//将降序排列

    ElemType t;

    LinkList p, q, s;//q,s比较

    if ((A->next) && (A->next->next))    //链表为空或只有一个结点时不用排序

    {

        p = A->next;

        while (p->next)

        {

            q = p->next;w

            s = p;

            while (q)

            {

                if (q->data > s->data)

                {

                    t = q->data;

                    q->data = s->data;

                    s->data = t;

                }

                q = q->next;

            }//endwhile 交换s结点和p结点的数据

            p = p->next;

        }//endwhile

    }//endif

    PrintDList(A);

}//endselectsort



void main()

{

    LinkList A=(LinkList)malloc(sizeof(LNode));

    LinkList B = (LinkList)malloc(sizeof(LNode));

    CreateDListTail(A);

    PrintDList(A);

    CreateDListTail(B);

    PrintDList(B);

    linkDList(A, B);

    selectsort(A);

    system("PAUSE");

    free(A);

    free(B);

}

代码通过VS 2013 + win 7 64 ;编译通过可运行,静态分析未通过,主要提示内存安全,API没返回值.

这个程序仅仅实现题目功能,一点都不完美.初学者能运行过谢天谢地了.

此外,代码的main部分应该可以简化吧,但是我不会.请前辈们指教.

 

补充需求:如果输入了自己原本不想输入的数据,应该再加点增加体验.

 

-----------------------------------------------------------------------------------------------------------------------------------

文章更新  150527

selectsort

问题目标:排序单链表

排除分析:链表只有0到1个结点不用排序 if ((A->next) && (A->next->next))   为什么这么写? A有头结点,头结点不算单链表的内容.

至于&&  这个操作符要求两边的表达式都是true整条表达式才是true 就是说满足不是空表且不只含一个结点才进行if体内的语句.可以看出我程序没有写这个if剩下的else,不知道在业界规范不.

思路:循环比较

1.任选一个结点作为基准 这里是p  p = A->next;  也就是链表A的第一个结点,p指向A的第一个,这个p以后会变成第二个第三个....

注意这个从前往后的过程 什么时候结束呢? while (p->next) 也就是p如果指向了最后一个结点就结束. 单链表的尾结点指针是NULL,这个NULL指向的数据域未知.

2.很明显有个内外遍历

外循环负责比较基准的后移,内循环负责比较的后移

难点:P到底什么用?

注意第15,此处是不能写s=s->next的,因为很可能s的值被换了,本来s是外部控制外部循环的,所以用p来跟踪外部循环的走向.

 1 while (p->next) //while外循环:遍历  2         {

 3             q = p->next;

 4             s = p;  //前两句保存两个指针,初始值一个是第一个,一个是第二个.q是内循环变量,所以下面的while要判断q是否为NULL,为NULL就说明这一轮比较完了,应该让s+1 ()

 5             

          while (q) //内循环:逐此比较 (4) 6 { 7 if (q->data > s->data)  //if语句比较q和s数据域的大小 里面是常用的交换代码(要用到中间变量) (6) 8 { 9 t = q->data; 10 q->data = s->data; 11 s->data = t; 12 } 13 q = q->next; //比较完了 q就后移一位,然后又回到if语句跟第一个进行比较:q是内循环变量 (5) 14 }//endwhile 15
p = p->next; //这么往后总会变NULL (2) 16 }//endwhile (1)

序号代码正常的思维过程和码代码过程.

你可能感兴趣的:(单链表)