数据结构之链表基本操作算法演示

本文介绍了单链表的基本操作,包括创建、遍历、插入、删除等算法,并提供了详细的C++实现代码。通过实例演示了如何运用这些算法解决实际问题。

最近在看数据结构,发现很多算法是看懂了,可是要写出来,并且实现它,并不是一件简单的事情,算法只是逻辑上的东西,程序是物理实践,不经过物理实践,你是不会发现其中的奥秘之处。后悔大学的时候,学了那么多的逻辑,都没有实践下。实践才能证明你的逻辑是否正确。以下是我对链表的温习后,新的实践。

// Win32Console.cpp : 定义控制台应用程序的入口点。
//
//单链表的创建,尾部插入方法

#include "stdafx.h"

#include "stdio.h"

typedef int elemtype;

typedef struct LNode
{
    elemtype Data;

    struct LNode *Next;
}LinkNode;

//尾部插入方法

LinkNode *CreateLinkList(int A[],int n)
{
      LinkNode *head,*p,*q;

      if(n < 0)
      {
          printf("The Arrary is empty!");
          return NULL;
      }

      head = new LinkNode();

      p = head ;

      printf("结点地址/t");

      printf("结点值域/t");

      printf("结点Next/t/n");

      for (int i = 0;i<n;i++)
      {
          //新结点申请
          q = new LinkNode();

          q->Data = A[i];

          p->Next = q;
       
          //跟踪结点的值和结点的地址及下个结点的地址。
          printf("%x/t/t",p);

          printf("%d/t/t",p->Data);

          printf("%x/t/t",p->Next);

          printf("/n");

          p = q;

      }

       printf("%x/t/t",p);

       printf("%d/t/t",p->Data);

       printf("%x/t/t",p->Next);

       printf("/n");

      return head; 
}

 

//头部插入结点建立单链表
LinkNode *CreateLinkListHead(int A[],int n)
{
    LinkNode *head,*p;

    if(n < 0)
    {
        printf("The Arrary is empty!");
        return NULL;
    }
    head = new LinkNode();

    //head->Next = NULL;默认的也是head->Next = NULL,所以可以不写。

    printf("结点地址/t");

    printf("结点值域/t");

    printf("结点Next/t/n");

    for(int i = 0;i < n; i++)
    {
        p = new LinkNode();

        p->Data = A[i];

        p->Next = head->Next;

       //跟踪结点的值和结点的地址及下个结点的地址。
       printf("%x/t/t",p);

       printf("%d/t/t",p->Data);

       printf("%x/t/t",p->Next);

       printf("/n");

       head->Next = p;
    }
       printf("%x/t/t",head);

       printf("%d/t/t",head->Data);

       printf("%x/t/t",head->Next);

       printf("/n");

    return head;
}

//获取链表的长度
int GetLength(LinkNode *head)
{
   int len = 0;
   while(head->Next != NULL)
   {
       len ++;
       head = head->Next;
   }
   return len;
}

//清空单链表
void ClearLinkList(LinkNode *head)
{
    head->Next = NULL;
}

//判断单链表是否为空,true表示为空,false表示不为空
bool IsEmpty(LinkNode *head)
{
    if(head->Next == NULL)
    {
        return true;
    }
    else
    {
        return false;
    }
}
//附加操作,即在单链表的表尾增加个结点
void Append(elemtype elem,LinkNode *head)
{
    LinkNode *q;

    while(head->Next != NULL)
    {
        head = head->Next;
    }
   
    q = new LinkNode();
   
    q->Data = elem;

    head->Next = q;

}

//单链表的插入操作,在指定位置的结点前插入
void InsertPre(LinkNode *head,int i,int value)
{
    LinkNode *p,*q;

    bool flag = false; //用来判断插入位置是否存在。

    int count = 1;

    p = head->Next;

    if(p == NULL || i<0)
    {
        printf("单链表为空,或插入位置不正确!/n");
        return;
    }
    if(i != 1)
    {
        while(p != NULL)
        {
            count++;

            if(count == i)
            {
                flag = true;
                break;
            }

            p = p->Next;
        }
        if(flag)
        {
            q = new LinkNode();

            q->Data = value;

            q->Next = p->Next;

            p->Next = q;
        }
        else
        {
            printf("插入位置不正确!/n");
        }
    }
    else
    {
        q = new LinkNode();

        q->Data = value;

        q->Next = head->Next;

        head->Next = q;
    }
}

//后插入操作,在指定位置的结点之后插入。
void InsertLast(LinkNode *head,int i,int value)
{
    LinkNode *p,*q;

    p = head->Next;

    int count = 1;

    bool flag = false;

    if(p == NULL || i < 0)
    {
        printf("单链表为空!或插入位置不正确/n");
        return;
    }
    while(p->Next != NULL)
    {
        if(count == i)
        {
            flag = true;
            break;
        }

        p = p->Next;

        count++;
    }
    if(flag)
    {
        q = new LinkNode();

        q->Data = value;

        q->Next = p->Next;

        p->Next = q;
    }
    else
    {
        printf("插入的位置不正确!/n");
    }

}

//删除操作,删除指定位置的结点
void Delete(LinkNode *head,int i)
{
    LinkNode *p,*q;

    p = head->Next;

    bool flag = false;

    int j = 1;

    if(p == NULL || i< 0)
    {
        printf("单链表为空或删除位置不正确!/n");

        return;
    }
    if(i == 1)
    {
        head->Next = p->Next;
        printf("删除结点的值为: %d/n",p->Data);
    }
    else
    {
       while(p != NULL)
        {
            if(j == i)
            {
               flag = true;

               break;
            }

            q = p;

            p = p->Next;

            j++;

        }
       if(flag)
       {
           q->Next = p->Next;

           printf("删除结点的值为: %d/n",p->Data);
       }
       else
       {
           printf("删除位置不正确!/n");
       }
    }

}

//取单链表指定位置的数据元素
void GetElem(LinkNode *head,int i)
{
    LinkNode *p;
    int count = 1;
    p = head->Next;
    bool flag = false;

    if(p == NULL || i < 0)
    {
        printf("单链表为空或i位置不正确!/n");

        return;
    }
   
    while(p != NULL)
    {
        if(count == i)
        {
            flag = true;
            break;
        }
        p = p->Next;
        count++;
    }
    if(flag)
    {
        printf("第i位置的数据元素为: %d",p->Data);

        printf("/n");
    }
    else
    {
        printf("链表中不存在第i个位置!");

        printf("/n");
    }
}

void Locate(LinkNode *head,elemtype T)
{
    LinkNode *p;

    p = head->Next;

    int count = 1;

    if(p == NULL)
    {
        printf("单链表为空!");

        return;
    }
    while(p != NULL)
    {
        if(p->Data == T)
        {
            printf("要查找的数值在单链表中首次出现的位置为: %d",count);
            printf("/n/n");
            return;
        }
        count++;
        p = p->Next;
    }
    printf("要查找的数值在单链表中不存在!/n/n");

}

 

//单链表的转置,返回转置后的单链表Head。通过后插入结点的方法。
void ReversLinkList(LinkNode *Head)
{
    LinkNode *p,*q,*r,*s;

    p = Head->Next;

    q = Head->Next->Next;

    int count = 1;

    if(p == NULL)
    {
        printf("单链表为空!/n");
        return;
    }
   
    p->Next = NULL; //新链表的尾部结点

    while(q != NULL)
    {  
        s  = new LinkNode();

        s->Data = q->Data;

        s->Next = p ;

        p = s;

        q = q->Next;
    }
   
    Head->Next = p;
}

//单链表的转置,返回转置后的单链表Head。算法2,通过移动结点指向。
void ReversLinkList2(LinkNode *head)
{
    LinkNode *p,*q,*s;

    p = head->Next; //指向链表的第一个结点

    q = p->Next;    //指向链表的第二个结点

    s = q->Next;    //指向链表的第三个结点

    p->Next = NULL; //作为新链表的尾部指针,Next域为NULL。

    while(q != NULL)
    {
        q->Next =  p;

        p = q;

        q = s;
       
        if(s != NULL)
        {
            s = s->Next;
        }
    }

    head->Next  = p;

}

//单链表的转置,采用遍历原先的单链表,插入到新的单链表中去,同时为了节省内存资源把原链表的头指针,作为新链表的头指针。
void ReversLinkList3(LinkNode *head)
{
    LinkNode *p,*q;

    p = head->Next;

    head->Next = NULL;

    q = new LinkNode();

    while(p != NULL)
    {
        q = p;

        p = p->Next;

        q->Next = head->Next;

        head->Next = q;
    }
}

//遍历单链表,并输出单链表的数据元素
void Print(LinkNode *head)
{
    LinkNode *p;

    p = head->Next;

    if(p == NULL)
    {
        printf("单链表为空!");
    }
    else
    {
        while(p != NULL)
        {
            printf("%d/t",p->Data);

             p = p->Next;
        }
    }
    printf("/n/n");
}


int _tmain(int argc, _TCHAR* argv[])
{
    LinkNode *p,*head;

    LinkNode *q,*headTop;

    int i ,value;

    int Arrary[] = {2,4,6,8,10};

    int Arrary1[] = {3,4,5,6,9,1,0};

    printf("******************************************************/n");

    printf("                单链表算法演示程序                    /n");
 
    printf("******************************************************/n/n");

    printf("【1】:测试尾部插入结点建立单链表/n");

    printf("【2】:测试头部插入结点建立链表/n");

    printf("【3】:链表的长度/n");

    printf("【4】:清空操作/n");

    printf("【5】:判断单链表是否为空/n");

    printf("【6】:追加操作,在单链表的表尾增加个元素/n");

    printf("【7】:在指定位置前,插入一个结点/n");

    printf("【8】:在指定位置之后,插入一个结点/n");

    printf("【9】:删除单链表中指定位置的结点/n");

    printf("【10】:取单链表中指定位置的数据元素/n");

    printf("【11】:按值查找算法演示/n");

    printf("【12】:单链表的转置算法演示(通过后插入结点的方法)/n");

    printf("【13】:单链表的转置算法演示(移动结点指向的方法)/n");

    printf("【14】:单链表的转置算法演示(采用遍历原单链表,插入到新的单链表中去)/n");

    printf("【0】:退出演示程序!/n/n");

START:

    printf("请输入要测试项的编号: ");

  

Goto:
    scanf("%d",&i);

    if(i == 0)
    {
        printf("按任何键退出程序.......");
    }
    else
    {

        printf("/n");

        switch(i)
        {
            case 1:
                printf("-------测试尾部插入结点建立链表---------/n");
                printf("/n");
                head = CreateLinkList(Arrary,5);   
                p = head->Next;

               /* printf("%x/n",head);*/

                printf("-----------遍历链表输出数据域-----------/n");

                while(p != NULL)
                {
                    printf("%d/t",p->Data);

                    p = p->Next;
                }
                printf("/n/n");

                goto START;

            case 2:
                printf("-------测试头部插入结点建立链表---------/n");
                printf("/n");

                headTop = CreateLinkListHead(Arrary1,7);

                q = headTop->Next;

                printf("-----------遍历链表输出数据域-----------/n");

                while(q != NULL)
                {
                    printf("%d/t",q->Data);

                    q = q->Next;
                }

                printf("/n/n");

                goto START;

            case 3:

                headTop = CreateLinkListHead(Arrary1,7);

                Print(headTop);

                printf("链表的长度为: ");

                printf("%d/n/n",GetLength(headTop));

                goto START;

            case 4:

                headTop = CreateLinkListHead(Arrary1,7);

                Print(headTop);

                printf("清空单链表2前,单链表头指针的Next域为:  ");

                printf("%x/n",headTop->Next);

                printf("清空单链表2后,单链表头指针的Next域为:  ");

                ClearLinkList(headTop);//清空操作
               
                printf("%x/n/n",headTop->Next);

                goto START;

            case 5:

                head = CreateLinkList(Arrary,5);

                Print(head);

                headTop = CreateLinkListHead(Arrary1,7);

                Print(headTop);

                printf("--------判断单链表是否为空-----------/n");

                if(IsEmpty(headTop))
                {
                    printf("单链表2为空!/n/n");
                }
                else
                {
                    printf("单链表2不为空!/n/n");
                }
                if(IsEmpty(head))
                {
                    printf("单链表1为空!/n/n");
                }
                else
                {
                    printf("单链表1不为空!/n/n");
                }

                goto START;

            case 6:

                head = CreateLinkList(Arrary,5);

                printf("---------追加操作,在单链表的表尾增加个元素--------/n");

                printf("追加数据元素前,单链表的数据元素为:/n");
               
                Print(head);

                Append(13,head);
                
                printf("追加数据元素后,单链表的数据元素为:/n");

                Print(head);

                printf("/n");

                goto START;

            case 7:

                head = CreateLinkList(Arrary,5);

                printf("在指定位置前,插入一个结点/n");

                printf("插入之前,单链表1的数据元素为: /n");

                Print(head);
               
                printf("请输入指定位置和插入值,格式为(i,value):");

                scanf("%d, %d",&i,&value);

                printf("/n");

                InsertPre(head,i,value);

                printf("插入之后,单链表1的数据元素为:/n");

                Print(head);

                goto START;

            case 8:

                head = CreateLinkList(Arrary,5);

                printf("在指定位置之后,插入一个结点/n");

                printf("插入之前,单链表1的数据元素为:/n");

                Print(head);

                printf("请输入指定位置和插入值,格式为(i,value):");

                scanf("%d, %d",&i,&value);

                printf("/n");

                InsertLast(head,i,value);

                printf("插入之后,单链表1的数据元素为:/n");

                Print(head);

                goto START;

            case 9:
           // default:

                head = CreateLinkList(Arrary,5);

                printf("删除单链表中指定位置的结点/n");

                printf("删除前,单链表1的数据元素为:/n");

                Print(head);

                printf("请输入删除结点的位置:(i):");

                scanf("%d",&i);

                printf("/n");

                Delete(head,i);

                printf("删除后,单链表中的数据元素为:/n");

                Print(head);

                goto START;

            case 10:

                head = CreateLinkList(Arrary,5);

                printf("取指定位置结点的数据元素:/n");

                printf("单链表目前的数据元素为:/n");

                Print(head);

                printf("请输入要取结点的位置:(i) ");

                scanf("%d",&i);

                GetElem(head,i);

                goto START;

            case 11:

                head = CreateLinkList(Arrary,5);

                printf("按值查找演示:/n");

                printf("单链表目前的数值元素为:/n");

                Print(head);

                printf("请输入要取查找的值:(value)");

                scanf("%d",&value);

                Locate(head,value);

                goto START;

            case 12:

                head = CreateLinkList(Arrary,5);

                printf("单链表转置算法演示:/n");

                printf("原单链表的数据元素为:/n");

                Print(head);

                printf("转置后的单链表的数据元素为:/n");

                ReversLinkList(head);

                Print(head);

                goto START;

            case 13:

                head = CreateLinkList(Arrary,5);

                printf("单链表转置算法演示:/n");

                printf("原单链表的数据元素为:/n");

                Print(head);

                printf("转置后的单链表的数据元素为:/n");

                ReversLinkList2(head);

                Print(head);

                goto START;

            case 14:

                head = CreateLinkList(Arrary,5);

                printf("单链表转置算法演示:/n");

                printf("原单链表的数据元素为:/n");

                Print(head);

                printf("转置后的单链表的数据元素为:/n");

                ReversLinkList3(head);

                Print(head);

                goto START;

            default:
                printf("编号输入错误,请重新输入 :");

                goto Goto;
        }
    }

    getchar();//如果不加此句,执行scanf("%d, %d",&i,&value);时,当输入两个值后,按下回车,会出先程序自动结束。

    getchar();//防止程序的自动结束。

 return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值