1.顺序表
//源文件,存放函数的实现
#include <stdio.h>
#include <assert.h>
#include "seqlist.h" //引用本项目的头文件
//初始化
void InitList(PSqList pl)
{
pl->length = 0;
//pl->elem;//不需要处理
}
//销毁顺序表
void Destroy(PSqList pl)
{
Clear(pl);
}
//清空,清除所有数据
void Clear(PSqList pl)
{
pl->length = 0;
}
//判空
bool IsEmpty(PSqList pl)
{
return pl->length == 0;
}
//判满,内部函数
static bool IsFull(PSqList pl)
{
return pl->length == MAXSIZE;
}
//获取长度
int GetLength(PSqList pl)
{
return pl->length;
}
//获取i下标的值
bool GetElem(PSqList pl, int i, ElemType* rtval)//O(1)
{
if (i < 0 || i>=pl->length) //失败
return false;
*rtval = pl->elem[i];
return true;
}
//获取i下标的前驱值
bool GetPrio(PSqList pl, int i, ElemType* rtval)
{
if (i <= 0 || i >= pl->length)
return false;
*rtval = pl->elem[i-1];
return true;
}
//获取i下标的后继值
bool GetNext(PSqList pl, int i, ElemType* rtval)
{
if (i < 0 || i >= pl->length - 1)
return false;
*rtval = pl->elem[i + 1];
return true;
}
//查找val的位置,返回下标,失败返回-1
int Seach(PSqList pl, int val)
{
for (int i = 0; i < pl->length; i++)
{
if (pl->elem[i] == val)
return i;
}
return -1;
}
//在i下标插入数据val
bool Insert(PSqList pl, int i, ElemType val)//O(n)
{
if (i<0 || i>pl->length || IsFull(pl))//i不合法,满
return false;
//把i及后面的数据后移
for (int j = pl->length - 1;j>=i; j--)
{
pl->elem[j + 1] = pl->elem[j];
}
//val存放在i下标
pl->elem[i] = val;
//处理pl->length
pl->length++;
return true;
}
//头插
bool Insert_head(PSqList pl, ElemType val)//O(n)
{
return Insert(pl,0,val);
}
//尾插
bool Insert_tail(PSqList pl, ElemType val)//O(1)
{
if (IsFull(pl))
return false;
pl->elem[pl->length] = val;
pl->length++;
return true;
}
//删除第一个val的值
bool Delete(PSqList pl, ElemType val)//O(n)
{
int index = Seach(pl,val);
if (index < 0)
return false;
for (int i = index; i <pl->length-1 ; i++)
{
pl->elem[i] = pl->elem[i + 1];
}
pl->length--;
return true;
}
//输出顺序表
void Show(PSqList pl)
{
for (int i = 0; i < pl->length; i++)
{
printf("%d ",pl->elem[i]);
}
printf("\n");
}
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "dsqlist.h"
没有头节点的顺序表
需要二次应用当遇到需要修改头指针形参**p,实参&p
//初始化
void InitList(PDSqList pl)
{
assert(pl != NULL);
pl->elem = (ElemType*)malloc(INIT_SIZE * sizeof(ElemType));
assert(pl->elem!=NULL);
if (pl->elem == NULL)
return;
pl->length = 0;
pl->size = INIT_SIZE;
}
//销毁顺序表
void Destroy(PDSqList pl)
{
free(pl->elem);
pl->elem = NULL;
pl->length = 0;
pl->size = 0;
}
//清空
void Clear(PDSqList pl)
{
pl->length = 0;
}
//判空
bool IsEmpty(PDSqList pl)
{
return pl->length == 0;
}
//获取长度
int GetLength(PDSqList pl)
{
return pl->length;
}
//获取i下标的值
bool GetElem(PDSqList pl, int i, ElemType* rtval)
{
if (i < 0 || i >= pl->length)
return false;
*rtval = pl->elem[i];
return true;
}
//获取i下标的前驱值
bool GetPrio(PDSqList pl, int i, ElemType* rtval);
//获取i下标的后继值
bool GetNext(PDSqList pl, int i, ElemType* rtval);
//查找val的位置,返回下标,失败返回-1
int Seach(PDSqList pl, int val);
static bool IsFull(PDSqList pl)
{
return pl->length == pl->size;
}
//扩容
static void Inc(PDSqList pl)
{
pl->elem = (ElemType*)realloc(pl->elem,2*pl->size*sizeof(ElemType));
assert(pl->elem != NULL);
pl->size *= 2;
}
//在i下标插入数据val
bool Insert(PDSqList pl, int i, ElemType val)//O(n)
{
if (i<0 || i>pl->length)
return false;
if (IsFull(pl))
{
Inc(pl);
}
//把i及后面的数据后移
for (int j = pl->length - 1; j >= i; j--)
{
pl->elem[j + 1] = pl->elem[j];
}
//把val放在i下标
pl->elem[i] = val;
pl->length++;
return true;
}
//头插
bool Insert_head(PDSqList pl, ElemType val)//O(n)
{
return Insert(pl,0,val);
}
//尾插
bool Insert_tail(PDSqList pl, ElemType val)//O(1)
{
return Insert(pl,pl->length,val);
}
//删除第一个val的值
bool Delete(PDSqList pl, ElemType val);
//输出顺序表
void Show(PDSqList pl)
{
for (int i = 0; i < pl->length; i++)
{
printf("%d ",pl->elem[i]);
}
printf("\n");
}
//放测试代码
#include <stdio.h>
#include <string.h>
#include "dsqlist.h"
//A=A n B
//例如:A={1,2,3,5,4};B={5,3,1} ;结果为{5,3,1}
void Merge(PDSqList pa, PDSqList pb)
{
for (int i = 0; i < GetLength(pa);)
{
if (Seach(pb, pa->elem[i]) == -1)//pb没有这个元素,需要删除
{
Delete(pa, pa->elem[i]);
}
else
i++;
}
}
//A=AUB,并集
//例如:A={1,2,3,5,4};B={5,3,1,8} ;AUB={1,2,3,4,5,8};
void Unio(PDSqList pa, PDSqList pb)
{
for (int i = 0; i < GetLength(pb); i++)
{
if (Seach(pa, pb->elem[i]) == -1)//不在,添加到pa
{
Insert_tail(pa,pb->elem[i]);
}
}
}
int main()
{
DSqList ds;
InitList(&ds);
for (int i = 0; i < 21; i++)
{
Insert(&ds,i,i);
}
Insert_head(&ds,-1);
Insert_tail(&ds,100);
Show(&ds);
return 0;
}
//#include "seqlist.h"
//
extern bool IsFull(PSqList);//引用外部符号
//
编译:只需要函数声明
链接:
//int main()
//{
// SqList sq;
// InitList(&sq);
//
// for (int i = 0; i < 20; i++)
// {
// Insert(&sq,i,i);
// }
// Insert_head(&sq,-1);
// Insert_tail(&sq,100);
// Delete(&sq,10);
// Show(&sq);
//
// return 0;
//}
2.链表
需要定位来进行操作
LNode表示任意节点
Llist表示头节点开始
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "list.h"
/*
*遍历链表所有节点总结:
* 1.需要前驱(需要修改链表结构) for(LNode *p=pl;p->next!=NULL;p=p->next) ...
* 2.不需要前驱,只遍历数据节点 for(LNode *p=pl->next;p!=NULL;p=p->next) ...
*/
//初始化
void InitList(LinkList pl)
{
assert(pl != NULL);
//pl->data,不使用
pl->next = NULL;
}
//销毁顺序表
void Destroy(LinkList pl)
{
LNode* p;
//总是删除第一个节点(食堂阿姨打饭)
while (pl->next != NULL)//还有第一个节点
{
p = pl->next;//保存第一个节点
pl->next = p->next;//剔除第一个节点
free(p);//删除第一个节点
}
//LNode* p = pl->next;
//LNode* q ;//p的后继
//pl->next = NULL;
//while (p != NULL)
//{
// q = p->next;
// free(p);
// p = q;
//}
}
//清空(原来的数据节点还要吗?,当前的设计是不要)
void Clear(LinkList pl)
{
Destroy(pl);
}
//判空
bool IsEmpty(LinkList pl)
{
return pl->next == NULL;//只有头节点
}
//获取长度(数据个数,不包括头节点)
int GetLength(LinkList pl)
{
int count = 0;
//遍历所有的数据节点
for (LNode* p = pl->next; p != NULL; p = p->next)
{
count++;
}
return count;
}
//获取i下标的值,设第一个数据节点的下标为0
bool GetElem(LinkList pl, int i, ElemType* rtval)//O(n)
{
if (i < 0 || i >= GetLength(pl))
return false;
int j = 0;
LNode* p;
for (p = pl->next; j < i; j++, p = p->next)
;//空语句
*rtval = p->data;
return true;
}
//获取i下标的前驱值
bool GetPrio(LinkList pl, int i, ElemType* rtval)//O(n)
{
if (i <= 0 || i >= GetLength(pl))
return false;
LNode* p;
int j = 0;
for (p = pl; j < i; ++j, p = p->next) //找到i的前驱节点
;
*rtval = p->data;
return true;
}
//获取i下标的后继值
bool GetNext(LinkList pl, int i, ElemType* rtval)//O(n)
{
if (i < 0 || i >= GetLength(pl) - 1)
return false;
int j=0;
LNode* p;
for (p = pl->next; j < i; ++j, p = p->next)//找到i下标的数据节点
;
*rtval = p->next->data;
return true;
}
//查找val的位置,返回节点地址,失败返回NULL
LNode* Seach(LinkList pl, int val)//LinkList ==LNode *,但是语义不同
{
for (LNode* p = pl->next; p != NULL; p = p->next)
{
if (p->data == val)
return p;
}
return NULL;
}
//在i下标插入数据val
bool Insert(LinkList pl, int i, ElemType val)
{
if (i<0 || i>GetLength(pl))
return false;
//创建新节点
LNode* p = (LNode*)malloc(sizeof(LNode));
assert(p != NULL);
if (p == NULL)
return false;
p->data = val;
//找到合适的位置
LNode* q;
int j = 0;
for (q = pl; j < i; ++j, q = q->next)
;
//插入,p插入在q的后面
p->next = q->next;
q->next = p;
return true;
}
//头插
bool Insert_head(LinkList pl, ElemType val)
{
//LNode newnode = {val}; //局部变量:生命周期(进入函数创建,函数结束销毁)
//newnode.next = pl->next;
//pl->next = &newnode;
LNode* p = (LNode*)malloc(sizeof(LNode));
assert(p!=NULL);
if (p == NULL)
return false;
p->data = val;
p->next = pl->next;
pl->next = p;
return true;
}
//尾插
bool Insert_tail(LinkList pl, ElemType val)
{
//创建新节点
LNode* p = (LNode*)malloc(sizeof(LNode));
assert(p != NULL);
if (p == NULL)
return false;
p->data = val;
//找尾巴
LNode* q;
for (q = pl; q->next != NULL; q = q->next)
;
//新节点插在尾巴的后面
p->next = q->next;//p->next = NULL;
q->next = p;
return true;
}
//删除第一个val的值
bool Delete(LinkList pl, ElemType val)
{
//LNode *p = Seach(pl,val);//不可以
//if (p == NULL)
// return false;
//1.找到val的前驱节点
LNode* p;
for (p = pl; p->next != NULL; p = p->next)
{
if (p->next->data == val)//找到了
break;
}
if (p->next == NULL)//没有找到
return false;
//2.把val节点从链表中剔除
LNode* q = p->next;//q就是将要删除的节点
p->next = q->next;//剔除q
//3.删除val节点
free(q);
return true;
}
//输出顺序表
void Show(LinkList pl)
{
for (LNode* p = pl->next; p != NULL; p = p->next)
{
printf("%d ",p->data);
}
printf("\n");
}