您的位置:首页 > 其它

LinkList 单链表的实现

2016-07-27 18:01 239 查看
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 的元素
//
db90
成功返回对应元素的结点的指针;否则返回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的头结点
}


以上内容来自《跟我学数据结构》陈锐 葛丽萍编著,尊重作者,购买图书。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: