实验二 线性表及其应用
(1) 编程实现顺序表的基本操作(建立、插入、删除、输出、顺序查找、折半查找、排序等),并设计一个菜单调用。
<sqlist.h>
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define FALSE 0
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
typedef int Status;
typedef int ElemType;
typedef struct {
ElemType *data;
int length;
int listsize;
}SqList;
Status InitList_Sq(SqList &L); //初始化顺序表
Status ClearList_Sq(SqList &L); //清空顺序表
Status EmptyList_Sq(SqList L); //顺序表的判空
Status DestroyList_Sq(SqList &L); //销毁顺序表
Status OutList_Sq(SqList L); //输出顺序表
Status LengthList_Sq(SqList L); //顺序表长度
Status Search_Sq(SqList L, ElemType e); //顺序查找
Status Search_Bin(SqList L, ElemType e); //折半查找
Status GetElem_Sq(SqList L, int i, ElemType &e); //按位置查找,并用e返回查找的值
Status InsertList_Sq(SqList &L, int i, ElemType e); //插入顺序表
Status Partition(SqList &L, int low, int high); //快速排序
Status QuickSort_Sq(SqList &L, int low, int high); //快速排序
Status DeleteList_Sq(SqList &L, int i, ElemType &e); //删除顺序表中选定的值,并用e返回删除的值
Status MergeList_Sq(SqList La, SqList Lb, SqList &Lc); //将两个顺序表合并为一个新的顺序表
<sqlist.cpp>
#include "sqlist.h"
//初始化顺序表
Status InitList_Sq(SqList &L) {
L.data = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));
if(!L.data) return FALSE;
L.length = 0;
L.listsize = LIST_INIT_SIZE;
return OK;
}
//清空顺序表
Status ClearList_Sq(SqList &L) {
L.length = 0;
return OK;
}
//对顺序表进行判空
Status EmptyList_Sq(SqList L) {
if(L.length == 0) return OK;
return FALSE;
}
//销毁顺序表
Status DestroyList_Sq(SqList &L) {
free(L.data);
L.length = 0;
L.listsize = 0;
return OK;
}
//输出顺序表
Status OutList_Sq(SqList L) {
for(int i = 1; i <= L.length; i++) {
printf("%d ",L.data[i-1]);
}
return OK;
}
//顺序表长度
Status LengthList_Sq(SqList L) {
return L.length;
}
//顺序查找,返回所在位置
Status Search_Sq(SqList L, ElemType e) {
int i;
L.data[L.length] = e;
for(i = 1; L.data[i-1] != e; i++);
if(i <= L.length) return i;
else return -1;
}
//折半查找,返回所在位置
Status Search_Bin(SqList L, ElemType e) {
int low = 1;
int high = L.length;
while(low <= high) {
int mid = (low + high)/2;
if(L.data[mid-1] == e) return mid;
else if(L.data[mid-1] > e) high = mid - 1;
else low = mid + 1;
}
return -1;
}
//按位置查找,并用e返回查找到的值
Status GetElem_Sq(SqList L, int i, ElemType &e) {
if(i < 1 || i > L.length) return FALSE;
e = L.data[i-1];
return OK;
}
//按位置插入顺序表
Status InsertList_Sq(SqList &L, int i, ElemType e) {
if(i < 1 || i > L.length+1) return FALSE;
if(L.length >= L.listsize) {
L.data = (ElemType *)realloc(L.data, (L.listsize + LISTINCREMENT) * sizeof(ElemType));
if(!L.data) return FALSE;
L.listsize += LISTINCREMENT;
}
int *q = &(L.data[i-1]);
int *p;
for(p = &(L.data[L.length-1]); p >= q; --p) *(p+1) = *p;
*q = e;
++L.length;
return OK;
}
//快速排序
Status Partition(SqList &L, int low, int high) {
ElemType pivot = L.data[low-1];
while(low < high) {
while(low < high && L.data[high-1] >= pivot) {
high--;
}
L.data[low-1] = L.data[high-1];
while(low < high && L.data[low-1] <= pivot) {
low++;
}
L.data[high-1] = L.data[low-1];
}
L.data[low-1] = pivot;
return low;
}
Status QuickSort_Sq(SqList &L, int low, int high) {
if(low < high) {
int pivotpos = Partition(L, low, high);
QuickSort_Sq(L, low, pivotpos-1);
QuickSort_Sq(L, pivotpos+1, high);
}
return OK;
}
//删除顺序表中的值,并用e返回删除的值
Status DeleteList_Sq(SqList &L, int i, ElemType &e) {
if(i < 1 || i > L.length) return FALSE;
int *q = L.data + L.length - 1;
e = L.data[i-1];
int *p;
for(p = &(L.data[i-1]); p < q; ++p) *p = *(p+1);
--L.length;
return OK;
}
//将两个顺序表合并为一个新的顺序表
Status MergeList_Sq(SqList La, SqList Lb, SqList &Lc) {
int *pa = La.data;
int *pa_last = La.data + La.length - 1;
int *pb = Lb.data;
int *pb_last = Lb.data + Lb.length - 1;
Lc.listsize = Lc.length = La.length + Lb.length;
int *pc = Lc.data = (ElemType *)malloc(Lc.listsize * sizeof(ElemType));
if(!Lc.data) return FALSE;
while(pa <= pa_last && pb <= pb_last) {
if(*pa <= *pb) *pc++ = *pa++;
else *pc++ = *pb++;
}
while(pa <= pa_last) *pc++ = *pa++;
while(pb <= pb_last) *pc++ = *pb++;
return OK;
}
<main.cpp>
#include "sqlist.h"
int main() {
printf("---------------SqList-----------------\n");
printf("1.创建顺序表 2.销毁顺序表\n");
printf("3.清空顺序表 4.顺序表判空\n");
printf("5.插入数据 6.删除数据\n");
printf("7.顺序查找 8.折半查找\n");
printf("9.快速排序 10.输出顺序表\n");
printf("11.顺序表长度 12.退出菜单\n");
printf("\n");
int flag = 1;
SqList L;
do{
printf("请输入选项 1 ——12:");
int order;
scanf("%d",&order);
int i; ElemType e;
switch(order){
case 1:InitList_Sq(L);
if(InitList_Sq(L) == 0) printf("创建顺序表失败!\n");
else printf("创建顺序表成功!\n");
printf("请向顺序表中输入5个数据:");
for(i = 1; i < 6; i++){
scanf("%d",&e);
InsertList_Sq(L,i,e);
}
break;
case 2:DestroyList_Sq(L);
printf("销毁顺序表成功!\n");
break;
case 3:ClearList_Sq(L);
printf("成功清空顺序表!\n");
break;
case 4:if(EmptyList_Sq(L) == 1) printf("顺序表为空\n");
else printf("顺序表不为空\n");
break;
case 5:printf("请输入插入的位置和数据值:");
scanf("%d %d",&i,&e);
InsertList_Sq(L,i,e);
break;
case 6:printf("请输入将要删除的位置:");
scanf("%d",&i);
DeleteList_Sq(L,i,e);
printf("删除位置的值为:%d\n",e);
break;
case 7:printf("输入将要进行顺序查找的数据:");
scanf("%d",&e);
if(Search_Sq(L,e) == -1) printf("该数据值不在顺序表中\n");
else printf("该数据值在顺序表中的位置为:%d\n",Search_Sq(L,e));
break;
case 8:printf("输入将要进行折半查找的数据:");
scanf("%d",&e);
if(Search_Bin(L,e) == -1) printf("该数据值不在顺序表中\n");
else printf("该数据值在顺序表中的位置为:%d\n",Search_Bin(L,e));
break;
case 9:QuickSort_Sq(L,1,L.length);
printf("成功完成快速排序");
break;
case 10:OutList_Sq(L);
break;
case 11:printf("顺序表长度为:%d",LengthList_Sq(L));
break;
case 12:flag = 0;
break;
}
printf("\n");
}while(flag);
return 0;
}
(2) 编程实现单链表的基本操作(建立、插入、删除、求表长、顺序查找、逆置、有序表的合并等),并设计一个菜单调用。
<linklist.h>
#include <stdio.h>
#include <stdlib.h>
#define OK 1;
#define FALSE 0;
typedef int Status;
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
}LNode, *LinkList;
//单链表的建立
Status InitList_L(LinkList &L);
//单链表的尾插法
Status InsertTail_L(LinkList &L);
//指定位置插入
Status InsertList_L(LinkList &L, int i, ElemType e);
//删除指定位置
Status DeleteList_L(LinkList &L, int i, ElemType &e);
//单链表长度
Status LengthList_L(LinkList L);
//顺序查找
Status SearchList_L(LinkList L, ElemType e);
//逆置
LinkList InsertHead_L(LinkList &L);
//有序表的合并
Status MergeList_L(LinkList La, LinkList Lb, LinkList &Lc);
//输出单链表
Status OutList_L(LinkList L);
<linklist.cpp>
#include "linklist.h"
//单链表的建立
Status InitList_L(LinkList &L) {
L = (LinkList)malloc(sizeof(LNode));
if(!L) return FALSE;
L->next = NULL;
return OK;
}
//单链表的尾插法
Status InsertTail_L(LinkList &L) {
LNode *q = L;
printf("在链表中插入几个数据:");
int m;
scanf("%d",&m);
printf("输入数据:");
for(int i = 0; i < m; i++) {
LNode *p = (LNode *)malloc(sizeof(LNode));
scanf("%d",&p->data);
q->next = p;
q = p;
}
q->next = NULL;
return OK;
}
//指定位置插入
Status InsertList_L(LinkList &L, int i, ElemType e) {
if(i < 1) return FALSE;
LNode *p = L;
int j = 0;
while(p && j < i-1) {
p = p->next;
j++;
}
if(!p) {
printf("超出链表的长度\n");
return FALSE;
}
LNode *r = (LNode *)malloc(sizeof(LNode));
r->data = e;
r->next = p->next;
p->next = r;
return OK;
}
//删除指定位置
Status DeleteList_L(LinkList &L, int i, ElemType &e) {
if(i < 1) return FALSE;
LNode *p = L;
int j = 0;
while(p->next && j < i-1) {
p = p->next;
j++;
}
if(!p->next) return FALSE;
LNode *s = p->next;
e = s->data;
p->next = s->next;
free(s);
return OK;
}
//单链表长度
Status LengthList_L(LinkList L) {
LNode *p = L;
int j = 0;
while(p->next) {
p = p->next;
j++;
}
return j;
}
//顺序查找
Status SearchList_L(LinkList L, ElemType e) {
LNode *p = L->next;
int i = 1;
while(p && p->data != e){
p = p->next;
i++;
}
if(!p) return -1;
else return i;
}
//逆置
LinkList InsertHead_L(LinkList &L) {
LinkList La;
InitList_L(La);
LNode *p = L->next;
while(p) {
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = p->data;
s->next = La->next;
La->next = s;
p = p->next;
}
return La;
}
//有序表的合并
Status MergeList_L(LinkList La, LinkList Lb, LinkList &Lc) {
LNode *pa = La->next;
LNode *pb = Lb->next;
LNode *pc = Lc = La;
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);
return OK;
}
//输出单链表
Status OutList_L(LinkList L) {
LNode *p = L->next;
while(p) {
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
<main.cpp>
#include "linklist.h"
int main(){ //建立、插入、删除、求表长、顺序查找、逆置、有序表的合并等
printf("---------------SqList-----------------\n");
printf("1.创建单链表表 2.插入单链表\n");
printf("3.删除单链表 4.单链表长度\n");
printf("5.顺序查找 6.逆置\n");
printf("7.有序表的合并 8.输出单链表\n");
printf("9.退出菜单\n");
printf("\n");
int flag = 1;
LinkList L;
do{
printf("请输入选项 1 ——9:");
int order;
scanf("%d",&order);
int i; ElemType e;
switch(order){
case 1:InitList_L(L);
if(InitList_L(L) == 0) printf("创建单链表失败!\n");
else printf("创建单链表La成功!\n");
printf("用尾插法向单链表中输入初始数据\n");
InsertTail_L(L);
break;
case 2:printf("请输入插入的位置和数据值:");
scanf("%d %d",&i,&e);
InsertList_L(L,i,e);
break;
case 3:printf("请输入将要删除的位置:");
scanf("%d",&i);
DeleteList_L(L,i,e);
printf("删除位置的值为:%d\n",e);
break;
case 4:printf("顺序表长度为:%d",LengthList_L(L));
break;
case 5:printf("输入将要进行顺序查找的数据:");
scanf("%d",&e);
if(SearchList_L(L,e) == -1) printf("该数据值不在顺序表中\n");
else printf("该数据值在顺序表中的位置为:%d\n",SearchList_L(L,e));
break;
case 6:printf("单链表进行逆置\n");
L = InsertHead_L(L);
break;
case 7:printf("创建一个新的单链表Lb\n");
LinkList Lb;
InitList_L(Lb);
printf("用尾插法向单链表Lb中输入初始数据\n");
InsertTail_L(Lb);
printf("单链表Lb为\n");
OutList_L(Lb);
printf("创建一个新的单链表Lc\n");
LinkList Lc;
InitList_L(Lc);
printf("将La表和Lb表进行合并得到新的单链表Lc\n");
MergeList_L(L, Lb, Lc);
printf("输出合并后的新链表Lc\n");
OutList_L(Lc);
break;
case 8:OutList_L(L);
break;
case 9:flag = 0;
break;
}
printf("\n");
}while(flag);
return 0;
}
(3) 编程实现双向循环链表的基本操作(建立、插入、删除、输出等),并设计一个菜单调用。
(4) 编程求解约瑟夫环(约瑟夫问题):已知n个人(以编号1,2,3…,n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
<DuLinkList.h>
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define FALSE 0
typedef int Status;
typedef int ElemType;
typedef struct DuLNode {
ElemType data;
struct DuLNode *next;
struct DuLNode *prior;
}DuLNode, *DuLinkList;
//初始化双向循环链表
Status InitList_Du(DuLinkList &L);
//插入双向循环链表
Status InsertList_Du(DuLinkList &L, int i, ElemType e);
//删除
Status DeleteList_Du(DuLinkList &L, int i, ElemType &e);
//长度
Status LengthList_Du(DuLinkList L);
//输出
Status OutList_Du(DuLinkList &L);
//约瑟夫问题
Status Create(DuLinkList &L);
Status visit(DuLinkList &L);
<DuLinkList.cpp>
#include "DuLinkList.h"
//初始化双向循环链表
Status InitList_Du(DuLinkList &L) {
L = (DuLinkList)malloc(sizeof(DuLNode));
if(!L) return FALSE;
L->next = L;
L->prior = L;
return OK;
}
//插入双向循环链表
Status InsertList_Du(DuLinkList &L, int i, ElemType e) {
if(i < 1) return FALSE;
DuLNode *p = L;
while(1) {
i--;
if(i == 0) break;
p = p->next;
}
DuLNode *q = (DuLNode *)malloc(sizeof(DuLNode));
q->data = e;
q->next = p->next;
p->next->prior = q;
p->next = q;
q->prior = p;
return OK;
}
//删除
Status DeleteList_Du(DuLinkList &L, int i, ElemType &e) {
if(i < 1) return FALSE;
DuLNode *p = L;
int j = 0;
while(p->next != L && j < i-1) {
p = p->next;
j++;
}
if(p->next == L) return FALSE;
DuLNode *s = p->next;
e = s->data;
p->next = s->next;
s->next->prior = p;
return OK;
}
//长度
Status LengthList_Du(DuLinkList L){
int i = 0;
DuLNode *p = L;
while(p->next != L){
i++;
p = p->next;
}
return i;
}
//输出
Status OutList_Du(DuLinkList &L) {
DuLNode *p = L->next;
while(p != L) {
printf("%d ",p->data);
p = p->next;
}
printf("\n");
return OK;
}
//约瑟夫问题
Status Create(DuLinkList &L) {
printf("请输入结点数:");
int n;
scanf("%d",&n);
DuLinkList tail = L;
DuLinkList p;
for(int i = 0; i < n; i++){
p = (DuLinkList)malloc(sizeof(DuLNode));
if(!p) return FALSE;
p->data = i+1;
tail->next = p;
p->prior = tail;
tail = p;
L->data++;
}
tail->next = L;
L->prior = tail;
return OK;
}
Status visit(DuLinkList &L){
int m,n,k;
n = L->data;
printf("请输入k和m以空格分开:");
scanf("%d %d",&k,&m);
int i = k;
int cnt =1;
while(L->next != L){
if(cnt == m){
cnt = 1;
int e;
DeleteList_Du(L,i,e);
printf("%d ",e);
i--;
}
else cnt++;
if(i == LengthList_Du(L)) i = 1;
else i++;
}
return 0;
}
<main.cpp>
#include "DuLinkList.h"
int main(){ //建立、插入、删除、输出等
printf("---------------DuLinkList-----------------\n");
printf("1.创建双向循环链表 2.插入双向循环链表\n");
printf("3.删除双向循环链表 4.输出双向循环链表 \n");
printf("5.约瑟夫环 6.退出菜单\n");
printf("\n");
int flag = 1;
DuLinkList L;
do{
printf("请输入选项 1 ——6:");
int order;
scanf("%d",&order);
int j; ElemType e;
switch(order){
case 1:InitList_Du(L);
if(InitList_Du(L) == 0) printf("创建双向循环链表失败!\n");
else printf("创建双向循环链表成功!\n");
for(int j = 1; j < 6; j++){
InsertList_Du(L, j, 2*j+1);
}
break;
case 2:printf("请输入插入的位置和数据值:");
scanf("%d %d",&j,&e);
InsertList_Du(L,j,e);
break;
case 3:printf("请输入将要删除的位置:");
scanf("%d",&j);
DeleteList_Du(L,j,e);
printf("删除位置的值为:%d\n",e);
break;
case 4:OutList_Du(L);
break;
case 5:DuLinkList La;
InitList_Du(La);
Create(La);
visit(La);
break;
case 6:flag = 0;
break;
}
printf("\n");
}while(flag);
return 0;
}