说明
使用数组存储,空间大小有限制,内存地址连续,可随机访问,一般不进行插入和删除操作,适合数据量确定和较小的情况。
代码
/*
** sqlist create by yubo.wang 2018.9.12
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 128
typedef char ElemType;
typedef struct
{
ElemType data[MAXSIZE];
int length;
}SqList;
void jose(int n, int m);
void InitList(SqList &L)
{
memset(L.data, 0, sizeof(L.data));
L.length = 0;
}
int GetLength(SqList L)
{
return L.length;
}
/*get data by index i,and save in e,return 0 if i invalid else 1*/
int GetElem(SqList L,int i,ElemType &e)
{
if(i<1 || i>L.length)
return 0;
else
{
e = L.data[i-1];
return 1;
}
}
/*find x and return index*/
int Locate(SqList L,ElemType x)
{
int i = 0;
while(L.data[i] != x)
i++;
if(i>L.length)
return 0;
else
return(i+1);
}
int InsElem(SqList &L,ElemType x,int i)
{
int j;
if(i<1 || i>L.length+1)
return 0;
for(j=L.length; j>i; j--)
L.data[j] = L.data[j-1];
L.data[i-1] = x;
L.length++;
return 1;
}
int DelElem(SqList &L, int i)
{
int j;
if(i<1 || i>L.length)
return 0;
for(j=i; j<L.length; j++)
L.data[j-1] = L.data[j];
L.length--;
return 1;
}
void DispList(SqList L)
{
int i = 0;
for(i=0; i<L.length; i++)
printf("%c ", L.data[i]);
printf("\n");
}
/*
C++ 函数传参:
(1) 将变量名作为实参和形参。这时传给形参的是变量的值,传递是单向的。如果在执行函数期间形参的值发生变化,并不传回给实参。因为在调用函数时,形参和实参不是同一个存储单元。// 同 c
(2) 传递变量的指针。形参是指针变量,实参是一个变量的地址,调用函数时,形参(指针变量)指向实参变量单元。这种通过形参指针可以改变实参的值。// 同 c
(3) C++提供了 传递变量的引用。形参是引用变量,和实参是一个变量,调用函数时,形参(引用变量)指向实参变量单元。这种通过形参引用可以改变实参的值。
*/
void swap(int& x, int& y)
{
int temp;
temp = x; /* 保存地址 x 的值 */
x = y; /* 把 y 赋值给 x */
y = temp; /* 把 x 赋值给 y */
return;
}
int vals[] = {10, 20, 30, 40, 50};
/*
(1)不能返回局部变量的引用。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。
*/
int& setValues( int i )
{
return vals[i]; // 返回第 i 个元素的引用
}
/* C++ 引用 vs 指针
不存在空引用。引用必须连接到一块合法的内存。
一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
引用必须在创建时被初始化。指针可以在任何时间被初始化。
*/
void fun_quote()
{
int i;
int& r = i;
i=1;
printf("%d,%d->", i,r);
r=2;
printf("%d,%d->", i,r);
int y=3;
r=y;//一旦引用被初始化为一个对象,就不能被指向到另一个对象,这里是指向其他对象了吗?
printf("%d,%d\n", i,r);
//C++ 把引用作为参数
int a = 100;
int b = 200;
printf("%d,%d->", a,b);
swap(a, b);
printf("%d,%d\n", a,b);
//C++ 把引用作为返回值
printf("%d,%d->", vals[1],vals[3]);
setValues(1) = 60; // 改变第 2 个元素
setValues(3) = 70; // 改变第 4 个元素
printf("%d,%d\n", vals[1],vals[3]);
}
int main()
{
int i;
ElemType e;
SqList L;
InitList(L);
InsElem(L,'a',1);
InsElem(L,'b',2);
InsElem(L,'c',3);
InsElem(L,'d',4);
InsElem(L,'e',5);
InsElem(L,'f',6);
printf("SqList: ");
DispList(L);
printf("length:%d\n", GetLength(L));
i=3;
GetElem(L,i,e);
printf("index %d data is:%c\n", i,e);
e='e';
printf("data %c index is:%d\n", e,Locate(L,e));
i=4;
printf("delete index %d data %c\n", i, L.data[i-1]);
DelElem(L,i);
i=2;
e='w';
printf("insert index %d data %c\n", i, e);
InsElem(L,e,2);
printf("SqList: ");
DispList(L);
jose(20, 5);
fun_quote();
return 0;
}
/*
** 求两个集合A和B的公共元素放在C中(单个集合中没有重复的元素)
*/
void common(SqList A,SqList B,SqList &C)
{
int i,j;
C.length = 0;
for(i=0; i<A.length; i++)
{
j=0;
while(j<B.length && B.data[j] != A.data[i])
j++;
if(j<B.length)
{
C.data[C.length++] = A.data[i];
}
}
}
/*
** 将两个有序递增A和B归并放在C中,时间复杂度O(A.length+B.length)
*/
void merge(SqList A,SqList B,SqList &C)
{
int i=0,j=0,k=0;
while(i<A.length && j<B.length)
{
if(A.data[i] < B.data[j])
{
C.data[k++] = A.data[i++];
}
else if(A.data[i] > B.data[j])
{
C.data[k++] = B.data[j++];
}
else
{
C.data[k++] = A.data[i++];
C.data[k++] = B.data[j++];
}
}
/*剩余的直接拷贝*/
while(i<A.length)
{
C.data[k++] = A.data[i++];
}
while(j<B.length)
{
C.data[k++] = B.data[j++];
}
C.length = k;
}
/*
** n只猴子选大王,所以猴子按1,2,...n编号坐一圈,从1号猴子开始按1,2...m报数,凡报到m号的退出圈外,如此循环直到最后一只就是大王
*/
void jose(int n, int m)
{
int mon[MAXSIZE];
int i,d,count;
/*给n只猴子编号*/
for(i=0; i<n; i++)
mon[i] = i+1;
/*打印初始值*/
printf("in:");
for(i=0; i<n; i++)
printf("%d ", mon[i]);
printf("\n");
/*打印出圈编号顺序*/
printf("out:");
count = 0;
i = -1;
while(count < n)//count出圈的个数->n
{
d=0;
while(d<m)//每一轮报数从d=0遍历到m
{
i=(i+1)%n;//i是保证从0->n->0的无线循环
if(mon[i] != 0)//遇已经出圈编号跳过遍历
d++;
}
printf("%d ", mon[i]);//打印出圈的编号
mon[i] = 0;//出圈编号值0标志
count++;//出圈的个数加1
}
printf("\n");
}