目录
目录
C / C++ 内存空间分类
1.代码区:存放函数体的二进制代码,由操作系统管理。
2.全局区:存放全局变量,静态变量和常亮。
3.栈区:编译器自动分配释放,存放函数的参数和局部变量等。
4.堆区:程序员分配和释放,若未释放,程序结束时有操作系统回收。
线性表--顺序表的实现
线性表—顺序表的实现
线性表是包含若干元素的线性序列 L=(D,R)
(D:元素数据集合 R:关系集合)
顺序存储:
(关于 typedef 函数的功能:重定义数据类型,如下列顺序存储结构 用typedef函数定义的名为sqlist的结构体,和名为sqlink的该结构体指针的名字 而非变量 。sqlist=struct sqlink L为定义一个名为L的结构体指针。)
程序框架
sqlist.h (头文件声明)
typedef int data_t;
#define N 128
typedef struct{
data_t data[N];
int last;
}sqlist,*sqlink;
sqlink list_create();
int list_clear(sqlink L);
int list_empty(sqlink L);
int list_length(sqlink L);
int list_locate(sqlink L,data_t value);
int list_insert(sqlink L,data_t,int pos);
int list_show(sqlink L);
int list_delete(sqlink L);
int list_shanchu(sqlink L,int pos);
int list_merge(sqlink L1,sqlink L2);
int list_purge(sqlink L);
功能实现:
(顺序表 空表的建立)
#include "sqlist.h"
#include <stdio.h>
#include <stdlib.h>//memset函数所需的头文件
#include <string.h>
sqlink list_create(){
//malloc 用malloc申请堆上空间
sqlink L;
L=(sqlink)malloc(sizeof(sqlist));
if(L==NULL){
printf("list malloc failed\n");
return L;
}
/*initialize 数据填充 用memset函数实现(功能: 将s所指向的某一块内存中的每个字节的内容全部
设置为ch指定的ASCII值,它是对较大结构体或数组清零的一种最快的方法。块的大小由第三个参数指
定,这个函数通常为新申请的内存做初始化工作
用 法: void *memset(void *s, char ch, unsigned n);)*/
memset(L,0,sizeof(sqlist));
L->last = -1;//定义空表因为数据是从0开始 将last定义为-1可以实现
//return
return L;
}
//列表清空
int list_clear(sqlink L){
if(L=NULL)
return -1;
memset(L,0,sizeof(sqlist));
L->last = -1;
return 0;
}
(检测是否为空表)
int list_empty(sqlink L){
if (L->last==-1)
return 1;
else
return 0;
}
(检测顺序表长度)
int list_length(sqlink L){
if(L==NULL)
return -1;
return (L->last+1);
return 0;
}
(顺序表数据定位)
int list_locate(sqlink L,data_t value){
int i ;
for (i = 0; i <= L->last; i++) {
if (L->data[i] == value)
return i;
}
return -1;
}
(数据插入)
int list_insert(sqlink L,data_t value,int pos){
int i;
//判断是否顺序表已满
if(L->last==N-1)
{
printf("list is full\n");
return -1;
}
// 判断输入位置顺序是否正确
if(pos<0||pos>L->last+1){
printf("pos is invalid\n");
return -1;
}
// 顺序表内数据移位 后一位等于前一位 last+1
for(i=L->last; i>=pos; i--){
L->data[i+1]=L->data[i];
}
//指定pos 填入数据
L->data[pos]=value;
L->last++;
return 0;
}
(数据的打印)
int list_show(sqlink L){
int i;
if(L == NULL)
return -1;
if (L->last==-1) //判断是否为空表
printf("list is empty\n");
//printf
for(i=0;i<=L->last;i++)
printf("%d ",L->data[i]);
puts("");
return 0;
}
(删除顺序表内某一位数据)
int list_shanchu(sqlink L,int pos){
int i;
//判断输入位置是否正确
if(pos<0||pos>L->last){
printf("shanchu error\n");
return -1;}
//判断是否是空表
if(L->last==-1){
printf("list is empty\n");
return -1;}
//其他数据移动
for (i=pos+1;i<=L->last;i++){
L->data[i-1]=L->data[i];
}
//更新
L->last--;
return 0;}
(顺序表的合并 **删除相同元素)
int list_merge(sqlink L1,sqlink L2){
int i=0;
int ret;
while (i <= L2->last){
ret = list_locate(L1, L2->data[i]);
if (ret == -1) {
if (list_insert(L1, L2->data[i],L1->last+1) == -1)
return -1;
}
i++;
}
return 0;}
(删除顺序表内相同元素)
int list_purge(sqlink L){
int i;
int j;
if(L->last==0)
return 0;
i=1;
while(i<=L->last){
j=i-1;
while(j>=0){
if (L->data[i]==L->data[j]){
list_shanchu(L,i);
break;
}
else{
j--;
}
}
if ( j < 0) {
i++;
}
}
return 0;
}
2.线性表--单链表
单链表的优缺点:
1.优点:
任意位置插入删除时间复杂度为O(1)。
没有增容问题,插入一个开辟一个空间。
缺点:
1.以节点为单位存储,不支持随机访问。
结构体的定义:(由数据域和后继指针域构成)
link.h(功能表)
typedef int data_t;
typedef struct node{
data_t data;
struct node *next;
}listnode, *linklist;
linklist list_create();
int list_tail_insert(linklist H,data_t value);//head
int list_insert(linklist H,data_t value,int pos);
linklist list_get(linklist H,int pos);
int list_show(linklist H);
list_create
#include <stdio.h>
#include <stdlib.h>
#include "linklist.h"
linklist list_create() {
linklist H;
H = (linklist)malloc(sizeof(listnode));//申请空间
if (H == NULL) {
printf("malloc failed\n");
return H;
}
H->data = 0;
H->next = NULL;
return H;
}
在尾部输入:
int list_tail_insert(linklist H, data_t value) {
linklist p;
linklist q;
//判断是否为空链表
if (H == NULL) {
printf("H is NULL\n");
return -1;
}
// 引入 p指针,并开辟新的空间 顺便判断是否成功
if ((p = (linklist)malloc(sizeof(listnode))) == NULL)
//“==”优先级大 于是申请空间要用括号
{
printf("malloc failed\n");
return -1;
}
p->data = value;//令p等于插入值
p->next = NULL;
//插入 链接
q = H;
while (q->next != NULL) {
q = q->next;
}
//3 insert
q->next = p; //植入数值
return 0;
}
打印:
int list_show(linklist H) {
linklist p;
if (H == NULL) {
printf("H is NULL\n");
return -1;
}
p = H;
while (p->next != NULL) {
printf("%d ", p->next->data);//逐位打印
p = p->next;
}
puts("");
return 0;
}
跳转指定位置:
linklist list_get(linklist H, int pos) {
linklist p;
int i;
// 链表 输入 判断
if (H == NULL) {
printf("H is NULL\n");
return NULL;
}
if (pos == -1) {
return H;
}
//跳转 for循环
p = H;
i = -1;
while (i < pos) {
p = p->next;
if (p == NULL)//位置超出判断
{
printf("pos is invalid\n");
return NULL;
}
i++;
}
return p;
}
指定位置插入字符
int list_insert(linklist H, data_t value, int pos) {
linklist p;
linklist q;
//链表是否为空?
if (H == NULL) {
printf("H is NULL\n");
return -1;
}
//1 locate node p (pos-1)定位到i-1的位置在后面插入
p = list_get(H, pos-1);
if (p == NULL) //超出位置判断
{
return -1;
}
//申请工具指针q的空间,并对申请结果是否成功判断
if ((q = (linklist)malloc(sizeof(listnode))) == NULL) {
printf("malloc failed\n");
return -1;
}
q->data = value;//插入数值
q->next = NULL;
//3 insert
q->next = p->next;//连接字符串,,先连后面
p->next = q;
return 0;
}
删除指定位置数据
int list_delete(linklist H,int pos){
linklist q;
linklist p;
// 判断
if (H==NULL){
printf("H is NULL\n");
return -1;
}
// 定位p指针位置
p=list_get(H,pos-1);
if (p==NULL)
return -1;
if(p->next==NULL)
{ printf("delete pos is invalid\n");
return -1;
}
// 更新
q=p->next;
p->next=q->next;
//4 free
printf("free:%d\n ",q->data);
free(q);
q=NULL;
return 0;
}
释放链表
linklist list_free(linklist H){
linklist p;
p=H;
if(H==NULL)
return NULL;
printf("free:\n");
while(H!=NULL){
p=H;
printf("%d ",p->data);
H=H->next;
free(p);
}
puts("");
return NULL;
}