declaration.h
#ifndef DECLARATION_H_INCLUDED
#define DECLARATION_H_INCLUDED
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define ElemType int
typedef ElemType* Triplet;
typedef int Status;
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
#endif // DECLARATION_H_INCLUDED
function.h
#ifndef FUNCTION_H_INCLUDED
#define FUNCTION_H_INCLUDED
void CreateList_L(LinkList *L, int n);
//逆序输入n个元素的值,简历带头结点的单链表L
Status ListInsert_L(LinkList *L , int i, ElemType e);
//在带头结点的单链线性表中第i个位置前插入元素e
Status ListDelete_L(LinkList *L, int i, ElemType e);
//在带头结点的单链线性表中,删除第i个元素并由e返回其值
Status GetElem_L(LinkList L, int i, ElemType *e);
//L为带头结点的单链表的头指针
//当第i个元素存在时将其值付给e并返回OK,否则返回ERROR
Status MergeList_L(LinkList *La, LinkList *Lb, LinkList *Lc);
//归并La和Lb表到Lc并按非递减序列排列
void PrintList_L(LinkList L);
//输出单链表中的内容
#endif // FUNCTION_H_INCLUDED
function.c
#include <stdio.h>
#include <stdlib.h>
#include "declaration.h"
void CreateList_L(LinkList *L, int n)
{
Status i;
LinkList p;
*L=(LinkList)malloc (sizeof(LNode));
(*L)->next=NULL; //先建立带头结点的单链表;->的优先级比*高不要漏掉这里的括号
for(i=n; i>0 ;i--)
{
p=(LinkList)malloc((sizeof(LNode)));//生成新节点
scanf("%d", &p->data);
p->next=(*L)->next; //插入到表头
(* L)->next=p; // 数据是倒着插入连表的,即最后输入的数在表头
}
}//CreateList_L
Status ListInsert_L(LinkList *L , int i, ElemType e)
{
LinkList p=*L, s;
ElemType j=0;
while( p && j < i-1)
{
p=p->next;
j++;
}
if(!p || j >i-1) return ERROR; //i小于1或大于表长加1
s=(LinkList)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s; //先连接后插入
return OK;
}
Status ListDelete_L(LinkList *L, int i, ElemType *e)
{
LinkList p=*L, q;
ElemType j=0;
while(p->next && j < 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 *e;
}
Status GetElem_L(LinkList L, int i, ElemType *e)
{
LinkList p;
ElemType j=1;
p=L->next;
while(p && j<i) //顺序查找直至p指向第i个元素或p为空
{
p=p->next;
j++;
}
if( !p || j>i) return ERROR; //第i个元素不存在
*e=p->data;
return *e;
}//GetElem_L()
Status MergeList_L(LinkList *La, LinkList *Lb, LinkList *Lc)
{
//La和Lb两个链表中数据非递减排列
//归并La和Lb表到Lc并按非递减序列排列
LinkList pa, pb, pc;
int i=0,j=0;
pa=(*La)->next; pb=(*Lb)->next;
printf("%x %x",(int )pa,(int )pb);
(*Lc) =(LinkList)malloc(sizeof(LNode));</span>
pc=(*Lc);
while( (int)pa && (int)pb)
{
if( (pa->data) <= (pb->data))
{
pc->next =pa;
pc=pa;
pa=pa->next;
}
else
{
pc->next=pb;
pc=pb;
pb=pb->next;
}
}
while( pa )
{
pc->next=pa;//插入剩余段
pc=pa;
pa=pa->next;
}
while( pb)
{
pc->next=pb;
pc=pb=NULL;
}
return OK;
}//MergeList_L()
void PrintList_L(LinkList L)
{
LinkList p;
for(p=L->next;p;p=p->next)//L为链表的头结点数据域没有赋值
printf("%d ",p->data);
printf("\n");
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include "declaration.h"
#include "function.h"
int main()
{
ElemType e;
LinkList *La, *Lb, *Lc;
La=(LinkList *)malloc(sizeof(LinkList));
Lb=(LinkList *)malloc(sizeof(LinkList));
Lc=(LinkList *)malloc(sizeof(LinkList));
printf("create la ,please enter 5 number:");
CreateList_L(La, 5);
printf("la=");
PrintList_L(*La);
printf("la表中第3个数是%d\n", GetElem_L(*La, 3, &e));
printf("删除la表中的第一个数是%d\n", ListDelete_L(La, 1,&e));
printf("after delete first member ,la=");
PrintList_L(*La);
printf("create lb ,please enter 4 number:");
CreateList_L(Lb, 4);
printf("lb=");
PrintList_L(*Lb);
ListInsert_L(Lb, 2, 3);
printf("after insert 3, lb =");
PrintList_L(*Lb);
printf("MergeList function ,Lc=\n");
if(MergeList_L(La, Lb, Lc) ==OK)
{
printf("merget success\n");
PrintList_L(*Lc);
}
else
printf("merget failed");
return 0;
}
分别定义二级指针La,Lb,Lc,将它们作为参数传递到CreateList_L()函数中,这样我们就可以在局部的函数里面为
*La, *Lb, *Lc分配存储空间,这些空间在结束函数调用时是不会消失的。C语言中参数传递都是值传递的方式:若以变量的值作为形参,传入的是一份值的拷贝。函数无返回类型时,对变量值得改变仅在该调用函数内有效;若以指针或数组名坐形参,传递的是变量的地址,同样的在调用函数内对这个地址的改变不会扩散到这个函数外,但对这个地址所代表的内存空间进行赋值,这种改变是永久的,结束调用时也不会被释放。
在实现MergeList_L(LinkList *La, LinkList *Lb, LinkList *Lc)时,一开始忘记为*Lc分配地址空间,使pc成为野指针,结果运行时程序一直挂掉浪费了好长一段时间。切记指针使用时一定要初始化。
运行结果: