贺胖娇的编程之旅......

线性表

2022.06.20

基础定义

数据元素存在一对一的关系,特点是数据元素按照某种规定存在一个顺序关系,数据元素需要是同一种类型

ADT

ADT List { 数据对象:{a~i|a~i∈ElementSet,i=1,2……n,n>=0}
数据关系:R1={<a~(i-1),a~i>|a~(i-1),a~i∈D,i=2,3…n} 基本操作:
1 结构初始化操作:线性表的建立
2 结构销毁操作:线性表的释放
3 引用型操作:查询,定位,找直接前驱和直接后继 4 加工型操作:插入、删除元素 }ADT List

基本操作

Status:枚举类型,操作结果

enum Status {
success, //成功
fail, //失败
fatal, //内部自己错误,例如内存分配失败
range_error, // 连续空间访问越界
}

ElemType:线性表的数据元素的类型
SqlListPrt:线性表L的数据类型

/* 初始化和销毁操作 */
Status List_Init(SqlListPtr L); //线性表初始化
void List_destroy(SqlListPrt L); //线性表销毁
void List_Clear(SqlListPrt L); //线性表清空

/* 引用型操作 */
bool List_Empty(SqlListPrt L); //线性表判空
int List_Size(SqlListPrt L); //获取线性表长度
Status List_Retrieval(SqlListPrt L, int pos, ElemType *elem); //从pos位置取数据,放到指针elem中
Status List_Locate(SqlListPrt L, ElemType elem, int *post); //定位elem在L中的位置,并把结果返回给pos
Status List_Prior(SqlListPrt L, int pos, ElemType *elem); //获取post位置元素的前驱并放入elem指针中
Status List_Next(SqlListPrt L, int pos, ElemType *elem); //获取post位置元素的后继并放入elem指针中

 
/* 加工型操作 */
Status List_Insert(SqlListPrt L, int pos, ElemType elem); //pos位置插入元素elem
Status List_Delete(SqlListPrt L, int pos); //pos位置删除元素

实例

合并线性表

问题

集合A和集合B分别用两个线性表LA和LB表示,求A∪B并用线性表LA表示

分析

算法设计思想:从LB中逐一取出元素,判断是否在LA中,若不在则插入LA中

实现

1 从LB中依次取出第i个元素:ListRetrieve(LB, i, &elem)
2 依次取出元素并判断在线性表a中是否存在:ListLocate(LA, elem, &j)
3 不存在则直接插入:ListInsert(La, 1, elem):元素插入到“1”这个位置

代码

根据以上步骤,使用go语言实现代码如下(原课程中使用c实现):

package main

import (
	"fmt"
)

func main()  {
	listA, err := TestListUnion()
	if err != nil {
		fmt.Printf("-2-----%v-\n", err)
	}
	fmt.Printf("ret is: %v\n", listA)
}

// BookList 由书籍信息组成的线性表
type BookList struct {
	BookNode map[int]BookManage `json:"book_node"`
}

// BookManage 书籍信息
type BookManage struct {
	Name   string `json:"name"`
	Year   string `json:"year"`
	Author string `json:"author"`
}

/**
合并线性表步骤:
1 从LB中依次取出第i个元素:ListRetrieve(LB, i, &elem)
2 依次取出元素并判断在线性表a中是否存在:ListLocate(LA, elem, &j)
3 不存在则直接插入:ListInsert(La, 1, elem):元素插入到“1”这个位置
 */

// TestListUnion 合并线性表
func TestListUnion() (BookList, error) {
	listA := BookList{
		BookNode: map[int]BookManage{
			0: {Name: "测试1", Year: "2011", Author: "author1"},
			1: {Name: "测试2", Year: "2012", Author: "author2"},
			2: {Name: "测试3", Year: "2013", Author: "author3"},
		},
	}
	listB := BookList{
		BookNode: map[int]BookManage{
			0: {Name: "测试4", Year: "2014", Author: "author4"},
			1: {Name: "测试5", Year: "2015", Author: "author5"},
			2: {Name: "测试6", Year: "2016", Author: "author6"},
			3: {Name: "测试2", Year: "2012", Author: "author2"},
		},
	}
	listBLen := len(listB.BookNode)
	for i := 0; i < listBLen; i++ {
		var tmpElem BookManage
		var tmpPos *int
		
		ListRetrieve(listB, i, &tmpElem)
		var pos int
		ListLocate(listA, tmpElem, &pos)
		tmpPos = &pos
		if *tmpPos > 0 {
			fmt.Printf("----2--repeart-----%v---%v\n", i, pos)
		} else {
			listA = ListInsert(listA, tmpElem)
		}
	}
	return listA, nil
}

// ListRetrieve 从LB中取出第i个元素
func ListRetrieve(listB BookList, i int, elem *BookManage) {
	elem.Name = listB.BookNode[i].Name
	elem.Year = listB.BookNode[i].Year
	elem.Author = listB.BookNode[i].Author
}

// ListLocate 获取元素是否存在,以及位置
func ListLocate(listB BookList, elem BookManage, j *int)  {
	var retPos int
	for key, elemItem := range listB.BookNode {
		if elemItem == elem {
			retPos = key + 1
			*j = retPos
		}
	}
}

// ListInsert 不存在则插入数据
func ListInsert(ListA BookList, elem BookManage) BookList {
	fmt.Printf("------4--1------%v\n", elem)
	// 这里只考虑在第一个位置插入数据,也就是 i 恒等于 0
	var newList BookList
	newListManage := make(map[int]BookManage)
	newListManage[0] = elem
	
	for key, elemItem := range ListA.BookNode {
		newListManage[key + 1] = elemItem
	}
	newList.BookNode = newListManage
	return newList
}

合并有序表

问题

已知线性表LA和LB都按非递减顺序排列,将两个线性表合成一个线性表LC,并且LC也按非递减顺序排列

分析

初始化LC为空,依次比较LA和LB中的元素,将较小的元素插入到LC末尾中,直到一个线性表扫描完毕,将另一个线性表的所有剩余元素依次插入到LC末尾中

代码

发表评论