数据结构(C语言版)-单链表

本程序实现了单链表的创建,结点的插入,删除,合并两个有序链表,求两个有序链表的交集,求两个有序链表的并集,求两个有序链表的差。
代码在VS2005编译下通过。有不当之处,不吝指教。QQ:381834158
// test2.cpp : 定义控制台应用程序的入口点。
//
#include<stdio.h>
#include <stdlib.h>
#include <string.h>
#include "stdafx.h"
#include <stack>
#include <conio.h>
#include <iostream>
typedef struct node
{
int n;
struct node *NEXT;
int size;
}NODE;
void menu();
NODE* CreateNode();
bool InitNode(struct node *pnode);
struct node *MakeNewNode();
void PrintNode(struct node *pnode);
NODE *InsertNode(NODE *pn);
void ElementInsert(NODE *newNode,int &iLocation);
NODE *DeleteNode(NODE *pnode);
void ElementDelete(int& iLocation);
NODE* MergeList(NODE *pnode);
NODE *Union(NODE *pl1);
NODE *ListIntersection(NODE *pl);
NODE *DivList(NODE *pl1);
void main()
    {
        char ch=0;
        NODE *head; //链表头结点
        head = CreateNode();
        menu();
        while ((ch=getchar())!='q')
        {
            
            switch(ch)
                {
            
            case 'i':
                InsertNode(head);
                menu();
                break;
            case 'p':
                PrintNode(head);
                menu();
                break;
            case 'd':
                DeleteNode(head);
                menu();
                break;
            case 'm':
                MergeList(head);
                menu();
                break;
            case 'u':
                Union(head);
                menu();
            case 's':
                ListIntersection(head);
                menu();
                break;
            case 'v':
                DivList(head);
                menu();
                break;
            default:
                break;
                }
        
        }
    
        
    }

void ElementDelete(int& iLocation)
    {
       puts("请输入要删除的元素的位置/n");
       scanf("%d",&iLocation);
    }

NODE *DeleteNode(NODE *pnode)
    {
       int p=1;
       int iLocation=0;
       NODE *head;
       head=pnode;
       NODE *q;
       ElementDelete(iLocation);
       while (pnode->NEXT&&p<iLocation-1)//前进到要删除结点的上一结点
       {
         p++;
         pnode=pnode->NEXT;
       }
       if(iLocation==0||iLocation>head->size)
       {
         puts("删除位置不合理");
         exit(0);
        }
      
       q=pnode->NEXT;
       pnode->NEXT=q->NEXT;
       head->size--;
       free(q);
       return head;
    }

void menu()
    {
       puts(" i)插入 d)删除 m)归并链表 /n u)求两个有序链表的并集 s)求两个有序链表的交集 v)求两个有序链表的差集/n p)打印");
    }

//
//从键盘获取要插入的位置和要插入的元素
//
void ElementInsert(NODE *newNode,int &iLocation)
    {
        puts("请输入结点元素(数字):/n");
        scanf("%d",&newNode->n);
        getchar();
        puts("请输入插入的位置");
        scanf("%d",&iLocation);
    }

//
//在第n个位置之后插入元素
//
NODE *InsertNode(NODE *pn)
    {
       NODE *head;
       head=pn;
       int iLocation=0;
       int p=1;
       NODE *newNode;
       newNode=MakeNewNode();
       ElementInsert(newNode,iLocation);
       while (pn&&p<iLocation) //前进到插入位置的前面那个结点
           {
               p++;
               pn=pn->NEXT;
           }
       if(iLocation==0||iLocation>head->size)//插入到第一个元素之前或者插入位置大于全部元素个数时中止
           {
             puts("插入位置不合理");
             exit(0);
           }
    
       newNode->NEXT=pn->NEXT;
       pn->NEXT=newNode;
       head->size++;
       return head;
     }

//
//打印全部结点
//
void PrintNode(struct node *pnode)
    {
      puts("结点信息:");
      while (pnode!=NULL)
      {
         printf("%d ",pnode->n);
         pnode=pnode->NEXT;//移动到下一个结点
        
      }
      puts("/n");
    }


//
//创建指定个数的结点
//
NODE *CreateNode()
    {
        int n=0;
        int number=0;
        struct node *head,*pcurrent;

        head=pcurrent=NULL;
        puts("请输入要创建的结点个数/n");
        scanf("%d",&n);
        struct node *newNode;
        for (int i=0;i<n;i++)
            {
                newNode = MakeNewNode();
                InitNode(newNode);
                puts("请输入结点元素(数字)");
                scanf("%d",&number);
                getchar();
                newNode->n=number;
                if (head==NULL)//如果是第一次创建结点,将新结点赋给头结点和当前结点
                    {
                        head=newNode;//头结点用来保存整个链表
                        pcurrent=newNode;
                    }
                else  //将新结点赋给当前结点

                    {
                        pcurrent->NEXT=newNode;
                        pcurrent=pcurrent->NEXT;
                        pcurrent->NEXT=NULL;

                    }
            
            }
        head->size=n;
        return head;
    }

//
//初始化结点
//
bool InitNode(struct node *pnode)
    {
      pnode->n=0;
      pnode->NEXT=NULL;
          return true;
    }



//
//给新结点分配内存空间
//
struct node *MakeNewNode()
    {

    struct node *newNode;

    newNode=(struct node*)malloc(sizeof(struct node));
    if (newNode==NULL)
        {
        puts("末能分配结点内存!");
        exit(1);
        }
    return newNode;
    }




//
//有序链表合并,将有序链表pl1和pl2合并到pc
//
NODE* MergeList(NODE *pl1)
    {

       NODE *pc,*pcHead;
       pc=MakeNewNode();
       pcHead=MakeNewNode();
       InitNode(pc);
       InitNode(pcHead);
       pcHead=pc;
       NODE *pl2;
       pl2 = CreateNode();
       pc->size=0;
       //pl1和pl2指向当前待比较插入的结点,pc指向表中最后一个结点.
       //如果pl2->n<pl1-n,将pl2所指的结点链入pc结点之后,否则将pl1所指的结点链入pc之后
       //当其中一个结点为空时跳出while循环
       while (pl1&&pl2)
           {
               if (pl2->n<pl1->n)
               {
                   pc->NEXT=pl2;
                   pc=pc->NEXT;
                   pl2=pl2->NEXT;

               }
               else
                   {
                       pc->NEXT=pl1;
                       pc=pc->NEXT;
                       pl1=pl1->NEXT;
                   }
              
                pc->size++;
           }
       pc->NEXT=pl1?pl1:pl2;//将剩余段链入pc中
       pc->size++;
      
      return pcHead;
    }

//
两个有序表求并集,将存在于表pl2和pl1中的元素并到表pc中
程序思路:依次比较两个有序链表结点指向的元素,将较小的元素所属结点链入新表后,
       该结点前进到下一结点(如果相等,则两个表都前进到下一结点),直到两个表都为空表。
      在表pl1或者表pl2不为空的前提条件下;
      跟据判断,如果表pl1为空,将pl2指向的结点逐个链入到表pc中,如果表pl2为空,将表pl1指向的结点逐个链入表pc中;
      如果两个表均不为空,而且结点元素相等,两个表都前进到下一个节点;
     如果pl1指向的结点元素小于表pl12,将表pl1指向的结点复制到表pc中,然后表p1前进到下一个结点
   否则,断定表pl2结点元素小于表pl1,因此将表pl2指向的结点复制到表pc中,然后前进到下一个结点
//
NODE *Union(NODE *pl1)
    {
        pl1->size=0;
        NODE *pc,*pcHead,*pl2;
        pc = MakeNewNode();
        pcHead = MakeNewNode();
        InitNode(pc);
        InitNode(pcHead);
        pl2 = CreateNode();
        pcHead = pc;
        
        while (pl1||pl2)
        {
          
           if (!pl1)//表pl1为空,则将pl2的结点赋给pc
           {
             pc->NEXT=pl2;
             pc=pc->NEXT;
             pl2=pl2->NEXT;//前进到下一个结点
           }
           else if (!pl2)
           {
             pc->NEXT=pl1;
             pc=pc->NEXT;
             pl1=pl1->NEXT;
           }
           else if (pl1->n==pl2->n)
           {
              pc->NEXT=pl1;
              pc=pc->NEXT;
              pl1=pl1->NEXT;
              pl2=pl2->NEXT;
           }
           else if (pl1->n<pl2->n)
           {
              pc->NEXT=pl1;
              pl1=pl1->NEXT;
              pc=pc->NEXT;
           }
           else
               {    
                  pc->NEXT=pl2;
                  pl2=pl2->NEXT;
                  pc=pc->NEXT;
                  pl1->size++;
               }
        }
       pc->NEXT=NULL;

        return pcHead;
    }


//
//求两个有序表的交集,将两个表中相同元素的结点链入到新表中
//
NODE *ListIntersection(NODE *pl1)
    {
    //程序思路,依次比较两个有序表中结点的元素,找到相等元素后将结点复制到新表。
    //然后两个表中的结点都前进到下一结点。比较两个表中的结点,每次元素小的表结点都前进到下一个结点。直到任何一个结点到达表尾。
    //在两个表均不为空的情况下,如果表pl1与表pl2结点中的元素相等,将表pl1结点复制到表pc中,
    //两个结点前进到下一个结点,如果表pl1的元素小于表pl2结点中的元素,该结点前进到下一结点,否则表pl2的结点前时到下一个元素,直到其中一个表为空。
        NODE *pc,*pcHead;
        pc=MakeNewNode();
        pcHead=MakeNewNode();
        InitNode(pc);
        InitNode(pcHead);
        pcHead=pc;
        NODE *pl2;
        pl2 = CreateNode();
        pc->size=0;
        while(pl1&&pl2)
        {
           if (pl1->n==pl2->n)
           {
               pc->NEXT=pl2;
               pc=pc->NEXT;
               pl1=pl1->NEXT;
               pl2=pl2->NEXT;
              
           }
           else if (pl1->n<pl2->n)
           {
              pl1=pl1->NEXT;
           }
           else
               {
                   pl2=pl2->NEXT;
               }
        }
        pc->NEXT=NULL;
        return pcHead;
    }

//
//求两个有序表的差集,将两个表中不同元素的结点链入到新表中
//
NODE *DivList(NODE *pl1)
    {
    
          pl1->size=0;
          NODE *pc,*pcHead,*pl2;
          pc = MakeNewNode();
          pcHead = MakeNewNode();
          InitNode(pc);
          InitNode(pcHead);
          pl2 = CreateNode();
          pcHead = pc;
          while (pl1 || pl2)
          {
             if (!pl1)
             {
                pc->NEXT=pl2;
                pc=pc->NEXT;
                pl2=pl2->NEXT;
             }
             else if (!pl2)
             {
                pc->NEXT=pl1;
                pc=pc->NEXT;
                pl2=pl2->NEXT;
             }
             else if (pl1->n==pl2->n)
             {
                pl1=pl1->NEXT;
                pl2=pl2->NEXT;

             }
             else if (pl1->n<pl2->n)
             {
                pc->NEXT=pl1;
                pc=pc->NEXT;
                  pl1=pl1->NEXT;
             }
             else
                 {
                    pc->NEXT=pl2;
                    pc=pc->NEXT;
                    pl2=pl2->NEXT;
                 }

          }
          pc->NEXT=NULL;
          return pcHead;

    }

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值