2.4 线性表的顺序表示和实现
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
#define ElemType int
#define ERROR 1
typedef struct
{
ElemType *elem;
int Length;
}SqList;
void InitList(SqList *L)
{
L->elem = (ElemType *)malloc(MAXSIZE * sizeof(ElemType));
if(!L->elem)
{
exit(ERROR);
}
L->Length = 0;
return;
}
void ListInsert(SqList *L, int i, ElemType e)
{
printf("在第%d位插入%d\n\n", i, e);
if(i<=0 || i > MAXSIZE)
{
exit(ERROR);
}
if(L->Length == MAXSIZE)
{
exit(ERROR);
}
for(int j=(L->Length) - 1;j >= i-1 ;j--)
{
L->elem[j+1] = L->elem[j];
}
L->elem[i-1] = e;
++ L->Length;
return;
}
void GetElem(SqList L, int i, ElemType *e)
{
if(i<=0 || i > L.Length)
{
exit(ERROR);
}
else
*e = L.elem[i-1];
return;
}
int LocateElem(SqList L, ElemType e)
{
for(int i=0;i<=L.Length;i++)
{
if(L.elem[i] == e)
{
return (i+1);
}
}
return 0;
}
void ListDelete(SqList *L, int i)
{
printf("删除第%d位元素\n\n", i);
if(i<=0 || i > L->Length)
{
exit(ERROR);
}
for(int j=0;i<=L->Length - 1;j++)
{
L->elem[j-1] = L->elem[j];
}
--L->Length;
return;
}
void DestroyList(SqList *L)
{
if(L->elem)
{
free(L->elem);
L->Length = 0;
printf("储存空间已释放\n\n");
}
return;
}
void ShowList(SqList L)
{
printf("线性表长度:%d\n", L.Length);
if(L.Length > 0)
{
printf("线性表为:");
for(int i=0;i<L.Length;i++)
{
printf("%d ", L.elem[i]);
}
printf("\n");
}
printf("\n");
}
int main(void)
{
SqList L;
InitList(&L);
ShowList(L);
ListInsert(&L, 1, 4);
ShowList(L);
ListInsert(&L, 1, 3);
ShowList(L);
/*
ElemType *e;
e = (ElemType *)malloc(sizeof(ElemType));
GetElem(L, 4, e);
printf("现在线性表第%d元素为%d.\n", 4, *e);
*/
printf("%d是线性表第%d位元素\n\n", 4, LocateElem(L, 4));
ListDelete(&L, 2);
ShowList(L);
DestroyList(&L);
return 0;
}
2.5 线性表的链式表示和实现
单向链表
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
#define ElemType char
#define ERROR 1
typedef struct LNode
{
ElemType data;
struct LNode *Next;
}LNode, *LinkList;
void InitList(LinkList *L)
{
*L = (LNode *)malloc(sizeof(LNode));
(*L)->Next = NULL;
printf("初始化成功");
return;
}
void CreateList_H(LinkList *L, int n)
{
*L = (LNode *)malloc(sizeof(LNode));
(*L)->Next = NULL;
LinkList p;
for(int i = 0; i < n; i++)
{
char temp;
p = (LNode *)malloc(sizeof(LNode));
printf("请输入第%d个节点数据:", i+1);
p->data = getchar();
temp = getchar();
p->Next = (*L)->Next;
(*L)->Next = p;
}
return;
}
void CreateList_R(LinkList *L, int n)
{
*L = (LNode *)malloc(sizeof(LNode));
(*L)->Next = NULL;
LinkList p, r = *L;
for(int i = 0; i < n; i++)
{
char temp;
p = (LNode *)malloc(sizeof(LNode));
printf("请输入第%d个节点数据:", i+1);
p->data = getchar();
temp = getchar();
p->Next = NULL;
r->Next = p;
r = p;
}
return;
}
void ListInsert(LinkList *L, int i, ElemType e)
{
LinkList s, p = *L;
int j = 0;
while(p && (j<i-1))
{
p = p->Next;
j++;
}
if(!p || j>i+1)
{
exit(1);
}
s = (LNode *)malloc(sizeof(LNode));
s->data = e;
s->Next = p->Next;
p->Next = s;
printf("在链表的第%d位置成功插入%c\n", i, e);
return;
}
void GetElem(LinkList L, int i, ElemType *e)
{
LinkList p = L->Next;
int j = 1;
while(p && j<i)
{
p = p->Next;
j++;
}
if(!p || j>i)
{
exit(1);
}
*e = p->data;
return;
}
LNode *LocateElem(LinkList L, ElemType e)
{
LinkList p = L->Next;//p指向首元结点
int j = 1;
while(p && p->data != e)
{
j++;
p = p->Next;
}
printf("%c在链表的%d号位置\n",e, j);
return p;
}
ElemType GetElem_V(LinkList L, int i)
{
LinkList p = L->Next;
int j = 1;
while(p && j<i)
{
p = p->Next;
j++;
}
if(!p || j>i)
{
exit(1);
}
return (p->data);
}
void ListDelete(LinkList *L, int i)
{
LinkList p = *L;
int j = 1;
while((p->Next) && (j<i-1)) //定位到第i号元素
{
p = p->Next;
j++;
}
if(!p || j>i)
{
exit(1);
}
LinkList q = p->Next;
p->Next = q->Next;
free(q);
printf("链表的%d号位置已删除\n",j);
return 0;
}
int main(void)
{
LinkList L, p;
ElemType e;
CreateList_R(&L, 4);
GetElem(L, 1, &e);
printf("第一个元素是%c\n", e);
ListInsert(&L, 1, 'a');
printf("第一个元素是%c\n", GetElem_V(L, 1));
LocateElem(L, 'q');
ListDelete(&L, 1);
printf("第一个元素是%c\n", GetElem_V(L, 1));
return 0;
}
双向链表
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
#define ElemType char
#define ERROR 1
typedef struct DuLNode
{
ElemType data;
struct DuLNode *prior;
struct DuLNode *next;
}DuLNode, *DuLinkList;
void CreateList_R(DuLinkList *L, int n)
{
*L = (DuLNode *)malloc(sizeof(DuLNode));
(*L)->next = NULL;
(*L)->prior = NULL;
DuLinkList p, r = *L;
for(int i = 0; i < n; i++)
{
char temp;
p = (DuLNode *)malloc(sizeof(DuLNode));
printf("请输入第%d个节点数据:", i+1);
p->data = getchar();
temp = getchar();
p->next = NULL;
r->next = p;
p->prior = r;
r = p;
}
r->next = *L;
return;
}
void ListInsert(DuLinkList *L, int i, ElemType e)
{
DuLinkList s, p = *L;
int j = 0;
while(p && (j<i-1))
{
p = p->next;
j++;
}
if(!p || j>i+1)
{
exit(1);
}
s = (DuLNode *)malloc(sizeof(DuLNode));
s->data = e;
s->next = p->next;
p->next->prior = s;
p->next = s;
s->prior = p;
printf("在链表的第%d位置成功插入%c\n", i, e);
return;
}
void ListDelete(DuLinkList *L, int i)
{
DuLinkList p = *L;
int j = 1;
while((p->next) && (j<i-1)) //定位到第i-1号元素
{
p = p->next;
j++;
}
if(!p || j>i)
{
exit(1);
}
DuLinkList q = p->next;
p->next = q->next;
q->next->prior = p;
free(q);
printf("链表的%d号位置已删除\n",j);
return;
}
void ShowList(DuLinkList L)
{
DuLinkList p = L->next;
int i = 1;
do{
printf("第%d号节点元素是%c\n", i, p->data);
p = p->next;
i++;
}while((p) != NULL);
return;
}
2.7线性表的应用
线性表的合并
void MergeList(SqList *LA, SqList LB)
{
int m = (*LA).Length, n = LB.Length;
ElemType e;
for(int i = 1;i <= n; i++)
{
GetElem(LB, i, &e);
if(!LocateElem((*LA), e))
{
ListInsert(LA, ++m, e);
}
}
return;
}
顺序有序表的合并
void MergeList_Sq(SqList LA, SqList LB, SqList *LC)
{
LC->Length = LA.Length + LB.Length;
LC->elem = (ElemType *)malloc(LC->Length * sizeof(ElemType));
ElemType *pa = LA.elem, *pb = LB.elem, *pc = LC->elem;
ElemType *pa_last = LA.elem + LA.Length - 1;
ElemType *pb_last = LB.elem + LB.Length - 1;
while((pa <= pa_last) && (pb <= pb_last))
{
if(*pa <= *pb)
{
*pc++ = *pa++; //建议写成pc = pa; pc++; pa++;程序是人的语言而不是机器的语言
}
else
{
*pc++ = *pb++;
}
}
while(pa <= pa_last)
{
*pc++ = *pa++;
}
while(pb <= pb_last)
{
*pc++ = *pb++;
}
}
顺序链表的归并
void MergeList_L(LinkList *LA, LinkList *LB, LinkList *LC) //按序合并链表
{
LinkList pa = (*LA)->Next;
LinkList pb = (*LB)->Next;
*LC = *LA;
LinkList pc = (*LC);
while(pa && pb)
{
if(pa->data <= pb->data)
{
pc->Next = pa;
pc = pa;
pa = pa->Next;
}
else
{
pc->Next = pb;
pc = pb;
pb = pb->Next;
}
}
pc->Next = pa ? pa : pb;
free(*LB);
}
void MergeList_Test(void)
{
printf("链表的归并测试\n\n");
LinkList LA, LB, LC;
CreateList_R(&LA, 3);
ShowList(LA);
CreateList_R(&LB, 4);
ShowList(LB);
MergeList_L(&LA, &LB, &LC);
ShowList(LC);
return;
}
2.8 案例分析与实现
#include<stdio.h>
#include<stdlib.h>
typedef struct PNode
{
float coef; //系数
int expn; //指数
struct PNode *next;
}PNode, *polynomial;
//多项式的创建
void CreatePoly(polynomial *P, int n)
{
*P = (PNode *)malloc(sizeof(PNode));
(*P)->next = NULL;
for(int i = 1;i <= n; i++)
{
polynomial s;
s = (PNode *)malloc(sizeof(PNode));
printf("请输入第%d项多项式的系数和指数,用半角逗号隔开:", i);
scanf("%f,%d", &(s->coef), &(s->expn));
polynomial pre = *P;
polynomial q = (*P)->next;
while(q && q->expn<s->expn) //定位到要插入的前一位
{
pre = q;
q = q->next;
}
s->next = q; //插入
pre->next = s;
}
}
void ShowPoly(polynomial P)
{
polynomial pp = P->next;
int i = 1;
while(pp)
{
printf("第%d项:系数为%.2f,指数为%d\n", i, pp->coef, pp->expn);
pp = pp->next;
i++;
}
return;
}
void AddPolyn(polynomial *Pa, polynomial *Pb)
{
polynomial p1 = (*Pa)->next;
polynomial p2 = (*Pb)->next;
polynomial p3 = Pa;
while(p1 && p2)
{
if(p1->expn == p2->expn) //指数相同,做相加工作
{
float sum = p1->coef + p2->coef;
if(sum) //若两系数之和不为0
{
p1->coef = sum;
p3->next = p1;
p1 = p1->next;
polynomial r = p2;
p2 = p2->next;
free(r);
}
else
{
polynomial r = p1;
p1 = p1->next;
free(r);
r = p2;
p2 = p2->next;
free(r);
}
}
else if(p1->expn < p2->expn)
{
p3->next = p1;
p3 = p1;
p1 = p1->next;
}
else
{
p3->next = p2;
p3 = p2;
p2 = p2->next;
}
}
p3->next = p1 ? p1 : p2;
free(*Pb);
}
int main(void)
{
polynomial test1_P, test2_P;
CreatePoly(&test1_P, 4);
ShowPoly(test1_P);
CreatePoly(&test2_P, 3);
ShowPoly(test2_P);
AddPolyn(&test1_P, &test2_P);
ShowPoly(test1_P);
return 0;
}
算法设计题
以下均在对应位置测试过
(1)
void MergeList_L(LinkList *LA, LinkList *LB, LinkList *LC) //按序合并链表
{
LinkList pa = (*LA)->Next;
LinkList pb = (*LB)->Next;
*LC = *LA;
LinkList pc = (*LC);
while(pa && pb)
{
if(pa->data < pb->data)
{
pc->Next = pa;
pc = pa;
pa = pa->Next;
}
else if(pa->data > pb->data)
{
pc->Next = pb;
pc = pb;
pb = pb->Next;
}
else
{
pc->Next = pb;
pc = pb;
pb = pb->Next;
LinkList r = pa;
pa = pa->Next;
free(r);
}
}
pc->Next = pa ? pa : pb;
free(*LB);
}
(2)
(3)
void InterList_L(LinkList *LA, LinkList *LB, LinkList *LC) //求交集
{
LinkList pa = (*LA)->Next;
LinkList pb = (*LB)->Next;
*LC = *LA;
LinkList pc = (*LC);
while(pa && pb)
{
if(pa->data == pb->data) //如果两链表值相等,储存在A中
{
pc->Next = pa;
pc = pa;
pa = pa->Next;
LinkList r = pb;
pb = pb->Next;
free(r);
}
else
{
LinkList r = pa;
pa = pa->Next;
free(r);
}
}
pc->Next = NULL;
while(pb)
{
LinkList r = pb;
pb = pb->Next;
free(r);
}
free(*LB);
}
void InterList_Test(void)
{
printf("链表的交集测试\n\n");
LinkList LA, LB, LC;
CreateList_R(&LA, 5);
ShowList(LA);
CreateList_R(&LB, 4);
ShowList(LB);
InterList_L(&LA, &LB, &LC);
ShowList(LC);
return;
}
(5)
按照大于d,小于d对长链表进行分解(之前我的链表是储存字符的,懒得改了)
void UnpackList(LinkList *LA, LinkList *LB, LinkList *LC) //分解链表,以字母d为界
{
LinkList pa = (*LA)->Next;
LinkList pb = *LB, pc = *LC;
while(pa)
{
if(pa->data < 'd')
{
pb->Next = pa;
pb = pa;
pa = pa->Next;
}
else if(pa->data > 'd')
{
pc->Next = pa;
pc = pa;
pa = pa->Next;
}
else
{
LinkList r = pa;
pa = pa->Next;
free(r);
}
}
pb->Next = NULL;
pc->Next = NULL;
free(*LA);
}
void UnpackList_Test(void)
{
printf("链表的分解测试\n\n");
LinkList LA, LB, LC;
CreateList_R(&LA, 10);
ShowList(LA);
InitList(&LB);
InitList(&LC);
UnpackList(&LA, &LB, &LC);
ShowList(LB);
ShowList(LC);
return;
}
(10)
这个暂时还有点问题,时间复杂度好像不是O(n),后面看情况再改。
void ListDelete_Item(SqList *L, ElemType e)
{
int size = L->Length;
for(int i = size - 1;i >= 0; i--)
{
if(L->elem[i] == e)
{
for(int j = i;j < L->Length; j++)
{
L->elem[j] = L->elem[j + 1];
}
L->Length--;
}
}
return;
}