实验二 线性表及其应用

本文介绍了如何实现顺序表、单链表和双向循环链表的基本操作,包括创建、插入、删除、长度计算和输出,同时展示了约瑟夫环问题的解决方法。通过菜单调用的形式,读者可以逐步掌握这些数据结构的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实验二 线性表及其应用
(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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值