LinkList 单链表的实现

LinkList.h

#include "stdio.h"
#include "math.h"
#include "malloc.h"
#include "stdlib.h"

//typedef int DataType;

//LinkNode是链表的结点类型,LinkList是指向链表的指针类型
//如果定义了 LinkList L;则定义了一个链表,L指向该链表的第一个结点
//不带头结点,链表为空,L=NULL;带头结点,链表为空,L->next = NULL;
typedef struct Node{
    DataType data;
    struct Node *next;
}LinkNode, *LinkList;


//初始化单链表,将单链表置空
//将单链表初始化为空。动态生成一个头结点,并将头结点的指针域置空
//根据typedef定义,LinkList 就是 ListNode* ,即 ListNode 的指针;
//根据InitList函数的形参声明,head 变量是 LinkList 类型的指针,即 ListNode 的二级指针。
//因此,*head 才是LinkList类型。
void InitList(LinkList *head) 
{
    if ((*head = (LinkList)malloc(sizeof(LinkNode))) == NULL)
        /*为头结点分配一个存储空间*/
        exit(-1);
        /* exit是一个进程,-1表示异常退出,要包含头文件 "stdlib.h" */
    (*head)->next = NULL;
}

//判断单链表是否为空,就是通过判断头结点的 指针域是否为空
//空返回 1 ; 否则返回 0;
int ListEmpty(LinkList head) 
{
    if (head->next == NULL)
        return 1;
    else
        return 0;
}

//按序号查找操作
//查找单链表中第i个结点。查找成功返回该结点的指针,否则返回NULL标志失败
LinkNode* Get(LinkList head, int i) {
    LinkNode *p;
    int j;
    if (ListEmpty(head))    //不为 0 表示链表为空
        return NULL;
    if (i < 1)              //判断序号是否合法
        return NULL;        
    j = 0;
    p = head;
    while (p->next != NULL && j < i) 
    {
        p = p->next;
        j++;
    }
    if (j == i) 
        return p;          //找到第 i 个结点,返回指针p;
    else
        return NULL;       //如果没找到第 i 个元素,返回NULL;
}


//按内容查找操作
//查找线性表中元素值为 e 的元素
//成功返回对应元素的结点的指针;否则返回NULL,表示失败
LinkNode* LocateElem(LinkList head, DataType e) 
{
    LinkNode* p;
    p = head->next;        //指针p指向第一个结点
    while (p)
    {
        if (p->data != e)
            p = p->next;
        else
            break;
    }
    return p;
}


//定位操作
//按内容查找并返回该结点的序号,称为定位函数
//查找线性表中元素值为 e 的元素,成功返回对应元素的序号,否则返回0;
int LocatePos(LinkList head, DataType e) 
{
    LinkNode* p;
    int i;
    if (ListEmpty(head))  //先判断链表是否为空
        return 0;
    p = head->next;      //指针p指向第一个结点
    i = 1;
    while (p) 
    {
        if (p->data == e)
            return i;
        else 
        {
            p = p->next;
            i++;
        }
    }
    if (!p)           //while 循环完也没有找到e,说明不存在e,返回0;
        return 0;
}


//插入操作
//在单链表中第i个位置插入一个结点,结点的元素值为e,插入成功返回1,失败返回0
int InsertList(LinkList head, int i, DataType e) 
{
    LinkNode *p, *pre;   //指针pre 是指向第i个元素的前驱结点,指针p指向新生成的结点
    int j;
    pre = head;
    j = 0;
    while (pre->next != NULL&&j < i - 1)     //为了找到第i-1个结点
    {
        pre = pre->next;
        j++;
    }
    if (j != i - 1)     //现在j应该等于 i-1,不等于说明没找到,插入位置错误
    {
        printf("插入位置错误");
        return 0;
    }
    if ((p = (LinkNode*)malloc(sizeof(LinkNode))) == NULL)    
        exit(-1);         //进程异常退出申请新结点失败
    p->data = e;
    //插入结点操作,顺序不能调换
    p->next = pre->next;
    pre->next = p;
    return 1;
}

//删除操作
//删除单链表中的第i个位置的结点。删除成功返回1,失败返回0
int DeleteList(LinkList head, int i, DataType *e) 
{
    LinkNode *p, *pre;
    int j;
    pre = head;
    j = 0;
    while (pre->next != NULL && pre->next->next != NULL && j < i - 1)
        /*判断是否找到前驱结点*/
    {
        pre = pre->next;
        j++;
    }
    if (j != i - 1)      //没有找到要删除的结点位置,说明删除位置错误
    {
        printf("删除位置错误");
        return 0;
    }
    //走到这里j=i-1
    //指针p指向单链表的第i个结点,并将该结点的数据域赋值给 e
    p = pre->next;
    *e = p->data;
    //将前驱结点的指针域指向要删除结点的下一个结点
    pre->next = p->next;
    //释放 p 指向的结点
    free(p);        
    return 1;
}

//求表长操作
//就是返回单链表元素个数
int ListLength(LinkList head) 
{
    LinkNode *p;
    int count = 0;
    p = head;
    while (p->next != NULL) 
    {
        p = p->next;
        count++;
    }
    return count;
}

//销毁链表操作  释放结点空间
void DestoryList(LinkList head) 
{
    LinkNode *p, *q;
    p = head;
    while (p != NULL)
    {
        q = p;
        p = p->next;
        free(q);
    }
}

这里写图片描述
这里写图片描述


存在两个单链表A和B,其中的元素都是非递减排列,编写算法归并单链表A和B,得到单链表C,C的元素值按照非递减排列。要求表C利用原来表A和B的结点空间,不申请额外空间

示例图

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

#define LISTSIZE 100
typedef int DataType;
#include "LinkList.h"

//将链表A和B的元素合并到C中的函数声明
void MergeList(LinkList A, LinkList B, LinkList *C);
void main()
{
    int i;
    DataType a[] = { 6,7,9,14,37,45,65,67 };
    DataType b[] = { 3,7,11,34,45,89 };
    LinkList A, B, C;
    LinkNode *p;
    InitList(&A);
    InitList(&B);
    InitList(&C);

    //将数组a中的元素插入到单链表A中
    for (i = 1; i <= (sizeof(a) / sizeof(a[0])); i++)
    {
        if (InsertList(A, i, a[i - 1]) == 0)
        {
            printf("位置不合法");
            return;
        }
    }
    //将数组b中的元素插入到单链表B中
    for (i = 1; i <= (sizeof(b) / sizeof(b[0])); i++)
    {
        if (InsertList(B, i, b[i - 1]) == 0)
        {
            printf("位置不合法");
            return;
        }
    }
    printf("单链表A中元素有%d个:\n", ListLength(A));
    for (i = 1; i <= ListLength(A); i++) 
    {
        p = Get(A, i);
        if (p)
            printf("%4d", p->data);
    }
    printf("\n");
    printf("单链表B中元素有%d个:\n", ListLength(B));
    for (i = 1; i <= ListLength(B); i++)
    {
        p = Get(B, i);
        if (p)
            printf("%4d", p->data);
    }
    printf("\n");
    MergeList(A, B, &C);
    printf("将单链表A和B合并到C后,C中的元素有%d个:", ListLength(C));
    for (i = 1; i <= ListLength(C); i++)
    {
        p = Get(C, i);
        if (p)
            printf("%4d", p->data);
    }
    printf("\n");
    system("pause");
}

/*单链表A和B中的元素非递减排列,将单链表A和B中的元素合并到C中,
  C中的元素仍然按照递减排列*/
void MergeList(LinkList A, LinkList B, LinkList *C) 
{
    LinkNode *pa, *pb, *pc;  //指向单链表A,B,C的指针
    pa = A->next;
    pb = B->next;
    *C = A;        //将单链表A的头结点作为C的头结点,此时不用释放A头结点
    (*C)->next = NULL;
    pc = *C;
    while (pa && pb)
    {
        if (pa->data <= pb->data)
        {
            //如果A中的元素小于或等于B中的元素,将A中的元素的结点作为C的结点
            pc->next = pa;
            //直接将指赋值给pc,包括了数据域和指针域
            pc = pa;
            pa = pa->next;
        }
        else
        {
            //如果A中的元素大于B中的元素,将B中的元素的结点作为C的结点
            pc->next = pb;
            pc = pb;
            pb = pb->next;
        }
    }
    pc->next = pa ? pa : pb;    //将剩余结点插入到C中
    free(B);                    //释放B的头结点
}

以上内容来自《跟我学数据结构》陈锐 葛丽萍编著,尊重作者,购买图书。

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include <stdio.h> #include <stdlib.h> #define ERROR -1 #define OK 1 //定义单链表 typedef char ElemType; typedef struct LNode // 结点类型定义 { ElemType data; struct LNode * next; }LNode, *LinkList;//LinkList为结构指针类型 //定义关于单链表的若干操作 //初始化--建空表 void InitList(LinkList *L) { *L = (LinkList)malloc(sizeof(LNode)); (*L)->next=NULL; } //尾插法建表 void create_tail(LinkList *L, int n) { LNode *p, *last; int i; last=(*L); for(i=1; i<=n; i++) { p=(LNode *)malloc(sizeof(LNode)); //产生一个新结点 fflush(stdin); //清空内存 scanf("%c", &p->data); //往新结点的数据域中存入元素 last->next=p; //将新结点接在最后一个结点的后面 last=p; //新结点成为最后一个结点 } last->next=NULL; } //求单链表的长度 int ListLength(LinkList L) { LNode *p; int length; p=L->next; //p指针指向第一个元素所在的结点 length=0; //用来存放单链表的长度 while( p!=NULL ) //结点存在 { p=p->next; //p指针向后移 length++; //个数增加1个 } return length; } //求特定元素的个数 int Count(LinkList L, ElemType x) { LNode *p; int length; p=L->next; //p指针指向第一个元素所在的结点 length=0; //用来计算特定元素的个数 while( p ) //结点存在 { if( p->data ==x) //如果找到特定元素,则个数加1 length ++; p=p->next; //p指针向后移 } return length; } //在第i个元素前插入 int ListInsert_L(LinkList *L, int i, ElemType e) { LNode *p, *s; int j; p=(*L); j=0; while( p &&j<i-1) //如果当前结点存在,且移动次数未达到所需次数(找第i-1个结点) { p=p->next; j++; } if(!p || j>i-1) return ERROR; s=(LNode *)malloc(sizeof(LNode)); //产生一新结点 s->data=e; //往新结点中存入元素 s->next=p->next; p->next=s; //新结点接在p结点之后 return OK; } //删除第i个元素 int ListDelete_L(LinkList *L, int i, ElemType *e) { LNode *p,*q; int j; p=(*L); j=0; while(p->next && j<i-1)//(找第i-1个元素)如果当前结点的下一个结点存在,且移动次数未达到所需次数 { p=p->next; j++; } if(!p->next || j>i-1) return ERROR; q=p->next; p->next=q->next; *e=q->data; free(q); //释放要删除的结点 return OK; } void reverse(LinkList *L) { LNode *p,*q,*r; p=(*L)->next; q=p->next; r=q->next; p->next=NULL; while(q!=NULL) { q->next=p; (*L)->next=q; p=q; q=r; if(r!=NULL) r=q->next; else break; } } void main() { LinkList list1; InitList(&list1); create_tail(&list1, 5); LNode *p; for(p=list1->next; p; p=p->next ) printf("%c ",p->data ); printf("\n"); /* printf("\n========================================\n"); printf("\n单链表的长度:%d\n", ListLength(list1)); printf("\n========================================\n"); printf("单链表中元素c的个数:%d\n", Count(list1, 'c')); printf("\n========================================\n"); ListInsert_L(&list1, 3, 'g'); printf("在第3个元素前插入元素g后,单链表中的元素有:\n"); for(p=list1->next; p; p=p->next ) printf("%c ",p->data ); printf("\n"); printf("\n========================================\n"); ElemType e; ListDelete_L(&list1,4, &e); printf("删除第4个元素后,单链表中的元素有:\n"); for(p=list1->next; p; p=p->next ) printf("%c ",p->data ); printf("\n"); printf("删除掉的元素是:%c\n",e); */ reverse(&list1); for(p=list1->next; p; p=p->next ) printf("%c ",p->data ); }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值